SwiftUI Horizontal ScrollView onTapGesture registering taps on vertical scrollview behind it

Viewed 668

I have a horizontal scrollview(ForEach) and vertical scrollview(ForEach) in a VStack when I scroll items from vertical scrollview(ForEach) and tap on the items from horizontal view then the tap gesture from horizontal view gets executed instead of tap gesture from vertical view.

here is my code :

//
//  TestView.swift
//  iOS
//
//

import SwiftUI

struct TestView: View {
    @State var searchTerm = ""
    
    
    var body: some View {
        VStack {
            TextField("Search",text: $searchTerm)
                .padding()
                .background(
                    RoundedRectangle(cornerRadius:15).fill(Color.yellow)
                )
                .padding()
            ScrollView(.horizontal){
                HStack{
                    ForEach(1..<100){ index in
                        VStack {
                            Image(systemName: "swift")
                                .resizable()
                                .scaledToFit()
                                .padding()
                                .frame(width: 100, height: 100, alignment: .center)
                                .background(Color.gray)
                                .clipShape(Circle())
                            Text("item \(index)")
                        }
                        .onTapGesture{
                            print("horizontal list item tapped")
                        }
                        
                    }
                    
                }
                
            }
            
            
            ScrollView {
                VStack {
                    ForEach(1..<100) { index in
                        HStack {
                            Image(systemName: "swift")
                                .resizable()
                                .scaledToFit()
                                .frame(width: 50, height: 50, alignment: .center)
                            Text("vertical list item : \(index)")
                            Spacer()
                        }
                        .contentShape(Rectangle())
                        .onTapGesture{
                            print("vertical list item \(index) tapped")
                        }
                        
                    }
                    .padding(.all,5)
                    .background(
                        RoundedRectangle(cornerRadius:15).fill(Color.gray)
                    )
                    .padding(.all,5)
                    
                }
            }
            
        }
        .animation(.easeIn(duration: 10))
    }
    
}

struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        TestView()
    }
}

before scrolling After scrolling

FYI: having list in the place of vertical scroll view fixed the tap gestures but I would like to have scrollview because I want to use ScrollViewReader to scroll vertical list items as next step

1 Answers

The solution is to add clipped content shape for both scrollviews, like

ScrollView(.horizontal){
     // .. content here
}.contentShape(Rectangle())
.clipped()

ScrollView {
     // .. content here
}.contentShape(Rectangle())
.clipped()

Tested with Xcode 12 / iOS 14

Related