Search code examples
xcodeswiftuiios13pickerswift5

SwiftUI How to add done button to picker


Ive make a mini app with just a button and a picker and the idea is to have a done button above the picker so once ive chosen a value i can press done and the picker will close.

I am aware if you click the "click me" button it will open and if you click it again close the picker but im looking for a button that appears with the picker and disapears with the clicker when clicked.

Almost like a toolbar above the picker with a done button

    @State var expand = false
    @State var list = ["value1", "value2", "value3"]
    @State var index = 0

    var body: some View {
       VStack {
            Button(action: {
                self.expand.toggle()
            }) {
                Text("Click me \(list[index])")
            }
            if expand {
                Picker(selection: $list, label: EmptyView()) {
                    ForEach(0 ..< list.count) {
                        Text(self.list[$0]).tag($0)
                    }
                }.labelsHidden()
            }

        }

enter image description here

enter image description here enter image description here

The third image is what im trying to accomplish and the first 2 are what ive currently got

Thank you for your help


Solution

  • Here is an approach how I would do this... of course tuning is still possible (animations, rects, etc.), but the direction of idea should be clear

    Demo of result:

    enter image description here

    Code:

    struct ContentView: View {
        @State var expand = false
        @State var list = ["value1", "value2", "value3"]
        @State var index = 0
    
        var body: some View {
           VStack {
                Button(action: {
                    self.expand.toggle()
                }) {
                    Text("Click me \(list[index])")
                }
                if expand {
                    Picker(selection: $index, label: EmptyView()) {
                        ForEach(0 ..< list.count) {
                            Text(self.list[$0]).tag($0)
                        }
                    }.labelsHidden()
                    .overlay(
                        GeometryReader { gp in
                            VStack {
                                Button(action: {
                                    self.expand.toggle()
                                }) {
                                    Text("Done")
                                        .font(.system(size: 42))
                                        .foregroundColor(.red)
                                        .padding(.vertical)
                                        .frame(width: gp.size.width)
                                }.background(Color.white)
                                Spacer()
                            }
                            .frame(width: gp.size.width, height: gp.size.height - 12)
                            .border(Color.black, width: 8)
                        }
                    )
                }
    
            }
        }
    }