Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I add section footer text below SwiftUI Picker options?

Tags:

ios

swiftui

I’m writing an app on SwiftUI and I use Picker to present a list of options for the user to choose.

I’d like to add some footer text to explain the choices in the list when someone taps into the picker and sees the options.

This is an example screenshot of what I’d like to accomplish, taken from the iOS Settings app: AirDrop settings

How can I achieve this with SwiftUI?

I define a footer for the Section that contains the Picker on the main screen ("Here is a short description of the setting.") and that works fine, but similar code does not add a footer on the screen that shows the Picker options.

Here’s my example code:

import SwiftUI

class ViewModel: ObservableObject {

    enum Option: String, Identifiable, CaseIterable, CustomStringConvertible {
        case optionOne
        case optionTwo
        case optionThree

        var id: Option {
            self
        }

        var description: String {
            rawValue.prefix(1).uppercased() + rawValue.dropFirst()
        }
    }

    @Published var selectedOption: Option = .optionOne {
        didSet {
            print("new option selected: \(selectedOption.description)")
        }
    }
}

struct ContentView: View {

    @ObservedObject var viewModel = ViewModel()

    var body: some View {

        NavigationView {
            Form {
                Section(footer: Text("Here is a short description of the setting.")) {
                    Picker(selection: $viewModel.selectedOption,
                           label: Text("Choice")) {
                            Section(footer: Text("This is some additional text to help the user understand the options.")) {
                                ForEach(ViewModel.Option.allCases) { type in
                                    Text(type.description)
                                }
                            }
                    }
                }

            }.navigationBarTitle(Text("Main Screen"))
        }
    }
}

Also, when this list loads I am seeing a weird jump. How can I avoid that?

like image 952
gohnjanotis Avatar asked Jan 21 '20 01:01

gohnjanotis


People also ask

How do I use SwiftUI header footer list tutorial?

Enter SwiftUIHeaderFooterListTutorial as the Product Name, select the Use SwiftUI checkbox, and click Next. Choose a location to save the project on your Mac. In the canvas, click Resume to display the preview. If the canvas isn’t visible, select Editor > Editor and Canvas to show it.

How to create custom list sections in Swift?

Creating List sections can be achieved by using a Section structure which also allows us to specify custom header and footer views. Finally, use the listStyle modifier to pick default system appearance for the List sections: Questions, comments or suggestions? Follow us on Twitter @theswiftguide

How do I hide empty rows in a SwiftUI list?

On top of that, we’re going to use a technique which hides empty rows in the List to make it look like this: SwiftUI List with custom section, header and a footer. This look can be achieved by using a ForEach structure which makes a view from an underlying data.

How do I extend a list with header and footer?

A List can be extended by adding a section with a header or footer. In this tutorial a list of cars is displayed with two different section headers and a footer text. SwiftUI requires Xcode 11 and MacOS Catalina, which the can be download at the Apple developer portal.


1 Answers

You may not need another dual footer, maybe just a hint title

struct ContentView: View {

    @ObservedObject var viewModel = ViewModel()

    var body: some View {

        NavigationView {
            Form {
                Section(footer: Text("Here is a short description of the setting.")) {
                    Picker(selection: $viewModel.selectedOption,
                           label: Text("Choice")) {

                            ForEach(ViewModel.Option.allCases) { type in
                                Text(type.description)
                            }.navigationBarTitle("hint title here", displayMode: .inline)

                    }
                }.navigationBarTitle("Main Screen", displayMode: .inline)

            }.navigationBarTitle(Text("Main Screen"))
        }
    }
}

Without a picker, you can build your own option lists:

struct ContentView: View {

    @ObservedObject var viewModel = ViewModel()

    var body: some View {

        NavigationView {
            Form {
                Section(footer: Text("Here is a short description of the setting.")) {
                    NavigationLink(destination: SelectionItemView(selection: $viewModel.selectedOption)) {
                        Text("Choice")
                    }


                }.navigationBarTitle("Main Screen", displayMode: .inline)

            }.navigationBarTitle(Text("Main Screen"))
        }
    }
}


struct SelectionItemView: View {

    @Binding var selection: ViewModel.Option
    var body: some View{
        Form{
            Section(footer: Text("Here is a detailed description of the setting.")) {
                ForEach(0 ..< ViewModel.Option.allCases.count, id: \.self) { index in

                    HStack{
                        Button(action: {
                            self.selection  = ViewModel.Option.allCases[index]
                        }){Text(ViewModel.Option.allCases[index].description)}
                        Spacer()
                        if ( self.selection  ==  ViewModel.Option.allCases[index] ){
                            Image(systemName: "checkmark")
                        }
                    }

                }
            }}


    }
}
like image 62
E.Coms Avatar answered Nov 03 '22 22:11

E.Coms