9

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?

Niklas
  • 23,674
  • 33
  • 131
  • 170
  • you only need to assign new selection value in your selectedIndex variable – YodagamaHeshan Jan 03 '21 at 11:49
  • What do you mean by 'open'? Is picker inside List ? – mahan Jan 13 '21 at 10:11
  • 1
    Can you add a more detailed / reproducible example? – pawello2222 Jan 13 '21 at 10:38
  • I do not think that it is a good idea to show the Picker over the views. Instead expand the row like the one in iOS Calenadar. This https://stackoverflow.com/questions/64919284/swiftui-animate-view-expansion-show-hide might help you. The question is mine and it works perfectly if your SuperView is not a List. – mahan Jan 13 '21 at 17:36
  • @pawello2222 I've updated the question, including screenshots and a copyable view – Niklas Jan 15 '21 at 11:13
  • @Niklas - do you need the narrow, red rectangle? And at that position? Or do you want the yellow "bar" only? – DonMag Jan 15 '21 at 20:33

3 Answers3

6

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

Niklas
  • 23,674
  • 33
  • 131
  • 170
4

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

DonMag
  • 69,424
  • 5
  • 50
  • 86
  • 2
    The `Picker` shows the current selected option instead of the label in iOS15 so the picker in no longer invisible. – runemonster Aug 23 '21 at 18:45
0

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