Niklas
Niklas

Reputation: 25413

SwiftUI Picker manually trigger expansion

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?

Upvotes: 9

Views: 2249

Answers (3)

Nikita Nikitin
Nikita Nikitin

Reputation: 59

A tricky solution is to use this


ZStack (alignment: .trailing) {
 ViewWhichYouWantToClick()

 Picker(selection: $pronouns, label: Text("")) {
       ForEach(themes,id:\.self) {
          Text($0)
       }
 }
 .opacity(0.02)
 .background(.clear)
 .accentColor(.white)
}
 

So the Picker is kinda invisible, but still clickable

Upvotes: 0

Niklas
Niklas

Reputation: 25413

@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.

Upvotes: 6

DonMag
DonMag

Reputation: 77482

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

Upvotes: 4

Related Questions