Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI Picker manually trigger expansion

Tags:

ios

swiftui

I've got the following view:

enter image description here

The Swift code looks like this:

struct TestView: View {
    let options = [" ", "1", "2", "3", "4", "5", "6"]
    @State var selectedIndex: Int = 0

    var body: some View {
        HStack(spacing: 0) {
            Text("One")

            Spacer()

            Picker(selection: $selectedIndex, label: Text(options[selectedIndex])) {
                ForEach(0 ..< options.count) {
                    Text(options[$0])
                }
            }
            .background(Color.red)
            .pickerStyle(MenuPickerStyle())
        }
        .padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
        .background(Color.yellow)
    }
}

When clicking on the red square, the Picker will be opened:

enter image description here

How can I extend the touch area of the red rectangle to also include the entire yellow area?

like image 597
Niklas Avatar asked Jan 03 '21 11:01

Niklas


2 Answers

Not sure this is exactly what you're after, but give it a try (initial view is a "blank" yellow bar):

import SwiftUI

struct PickerTestView: View {
    let options = [" ", "1", "2", "3", "4", "5", "6"]
    let optionNames = [" ", "One", "Two", "Three", "Four", "Five", "Six"]
    @State var selectedIndex: Int = 0

    var body: some View {
        ZStack {
            HStack(spacing: 0) {
                Text(optionNames[selectedIndex])
                Spacer()
            }
            .padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
            .background(Color.yellow)
            HStack(spacing: 0) {
                Picker(selection: $selectedIndex, label: Text(" ").frame(maxWidth: .infinity), content: {
                    ForEach(0 ..< options.count) {
                        Text(options[$0])
                    }
                })
                .pickerStyle(MenuPickerStyle())
            }
        }
    }

}

struct PickerTestView_Previews: PreviewProvider {
    static var previews: some View {
        PickerTestView()
    }
}

On launch:

enter image description here

Tap anywhere on the yellow bar:

enter image description here

After selecting "3":

enter image description here

like image 193
DonMag Avatar answered Oct 19 '22 11:10

DonMag


@DonMag's answer stopped working with iOS 15. Here's an updated answer that does work. Technically, it does not use Slider, the behavior is the same though. Instead a Menu is used.

struct PickerTestView: View {
    let options = [" ", "1", "2", "3", "4", "5", "6"]
    let optionNames = [" ", "One", "Two", "Three", "Four", "Five", "Six"]
    @State var selectedIndex: Int = 0

    var body: some View {
        ZStack {
            HStack(spacing: 0) {
                Text(optionNames[selectedIndex])
                Spacer()
            }
            .padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
            .background(Color.yellow)

            HStack(spacing: 0) {
                Menu {
                    ForEach(0 ..< options.count) {
                        let index = $0
                        Button("\(options[index])") {
                            selectedIndex = index
                        }
                    }
                } label: {
                    Label("", image: "")
                        .labelStyle(TitleOnlyLabelStyle())
                        .frame(maxWidth: .infinity)
                }
            }
        }
    }
}


struct PickerTestView_Previews: PreviewProvider {
    static var previews: some View {
        PickerTestView()
    }
}

Let's see when Apple decides to break this implementation.

like image 34
Niklas Avatar answered Oct 19 '22 10:10

Niklas