leonboe1
leonboe1

Reputation: 1185

SwiftUI unexpected index with ForEach Loop and Picker

I want to build a custom List which allows the User to select one entry leading to a Picker to show up.

Because the Picker takes up more space than the default entry, the other elements in the List should move accordingly. I used a ForEach loop and a VStack to achieve that goal.

However, sometimes the onTapGesture doesn't do anything. Debugging my code, I found out that the onTapGesture works like it should - but the index of the tapped entry is wrong. See the GIF below: Clicking on the "1" and "2" should lead to an output of index "1" and "2" but that's not the case. Does anybody know why? Thanks a lot!

enter image description here

struct ContentView: View {
    @State var timeList: [Int] = [1, 2, 3]
    @State var selectedElement = 0
    @State var sec = 0
    
    var body: some View {
        ScrollView(){
            VStack{
                ForEach(timeList, id: \.self){ elem in
                    ZStack{
                        VStack{
                            
                            ZStack{
                                Rectangle()
                                    .cornerRadius(elem == self.selectedElement ? 20 : 50)
                                    .frame(height: elem == self.selectedElement ? 120 : 40)
                                    .foregroundColor(Color.gray.opacity(0.3))
                                    .padding()
                                
                                Text("\(elem)").opacity(elem == self.selectedElement ? 0 : 1)
                            }
                        }
                        
                        if(elem == self.selectedElement){
                            HStack{
                                Spacer()
                                
                                Picker(selection: self.$sec, label: Text("")){
                                    Text("abc")
                                }
                                
                                Spacer()
                            }
                        }
                    }
                    .frame(height: elem == self.selectedElement ? 100 : 30)
                    .padding()
                    .onTapGesture {
                        withAnimation(.spring()){
                            self.selectedElement = elem
                            print(self.selectedElement)
                        }
                    }
                }
            }
            Spacer()
            
            Button(action: {
                self.timeList.append(5)
            })
            {
                Text("add")
            }
        }
        
    }
}

Upvotes: 1

Views: 274

Answers (1)

Asperi
Asperi

Reputation: 257749

Everything's fine with your code, you just tapped in transparent space, which is not handled by default.

Here is fix - just made entire area hit-available (tested with Xcode 12 / iOS 14)

.contentShape(Rectangle())    // << fix !!
.onTapGesture {
    withAnimation(.spring()){
//        print(elem)     // << here if you want
        self.selectedElement = elem
    }
}

Upvotes: 1

Related Questions