Search code examples
iosswiftswiftuiswiftui-form

SwiftUI Form Icons


Sorry if this is a really stupid question and maybe offtopic, but I can't seem to find it anywhere.

I'm trying to do a simple settings section for my app and would like to add icons to my elements so users can easily understand what does each setting does. To achieve that, I used Horizontal Stacks (HStack) with an Image and a Label (Text).

This somehow does the trick but I'd like to know if there's a cleaner way to do this. I'd also like to know how to adjust the separator between cells to stop on the label, and not continue until the end of the element.

As I'm not really good at explaining, here you have two images:

This is what I got enter image description here

I'd like to have something similar to this enter image description here

My code:

SettingsView.swift

struct SettingsView: View {

    @State var age: Int = 0

    var body: some View {
        UITableView.appearance().separatorStyle = .singleLine

        UINavigationBar.appearance().shadowImage = UIImage()

        return NavigationView {

            Form {

                Section {
                    Picker(selection: .constant(1), label: HStack {

                        Image(systemName: "paintbrush")
                            .font(Font.system(size: 25, weight: .light))

                        Text("Editor Theme")
                    }) {
                        Text("Ayu Mirage").tag(1)
                        Text("Ayu Light").tag(2)
                    }
                    Stepper(value: self.$age,
                            in: 18...100,
                            label: {
                                HStack {

                                    Image(systemName: "rectangle.stack")
                                        .font(Font.system(size: 25, weight: .light))

                                    Text("Number of snippets: \(self.age)")
                                }
                    })

                    NavigationLink(destination: NotificationSettingsView()) {
                        HStack {
                            Image(systemName: "app.badge")
                                .font(Font.system(size: 25, weight: .light))

                            Text("Notifications")
                        }
                    }

                }

                Section {
                    VStack(alignment: .leading, spacing: 5) {
                        Text("Mercury v1.0")
                            .font(.headline)
                        Text("Designed with ❤️ by amodrono")
                            .font(.footnote)
                    }.padding(.vertical, 5)
                }

            }

            .navigationBarTitle("Hello")
            .environment(\.horizontalSizeClass, .regular)
            .navigationBarTitle(Text("Settings"), displayMode: .inline)
            .navigationBarItems(leading: (
                Button(action: {
                }) {
                    Image(systemName: "xmark")
                        .font(.headline)
                        .imageScale(.large)
                        .foregroundColor(Color(UIColor(named: "adaptiveColor")!))
                }
            ))

        }
    }
}

Solution

  • You can disable the separator from the tableview and add your own divider.

    Something like this:

    struct ContentView: View {
        var body: some View {
            UITableView.appearance().separatorStyle = .none
            return NavigationView { 
                Form { 
                    Section { 
                        RowView(iconName:"rectangle.stack", text:"Some text")
                        RowView(iconName:"paintbrush", text:"Some other text", showDivider: false)
                    }
                }
            }
        }
    }
    
    struct RowView: View {
        var iconName: String
        var text: String
        var showDivider = true
        var body: some View {
            HStack(alignment: .firstTextBaseline) {
                Image(systemName: iconName)
                VStack(alignment: .leading) { 
                Text(text)
                    if showDivider { 
                        Divider()
                    } else {
                        Spacer()
                    }
                }
            }
        }
    }
    

    enter image description here