[SOLVED] SwiftUI Horizontal ScrollView onTapGesture is Off

Issue

I am experiencing some very odd behavior from a Horizontal ScrollView, it seems as if the clickable frame of the cells are offset. For example, if you click on left half of the first cell it will register the click for the first cell, but if you click the right half of the first cell it will register a click on the second cell. I’m not sure why this is happening.

I’ve included the code below, you can copy and paste this code into a playground to reproduce the issue. Any ideas here?

struct TestView: View {
    
    var image: String
    
    var body: some View {
            ZStack {
                Image(systemName: image)
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width: 104, height: 168)
                    .cornerRadius(8)
                    .clipped()
                
                VStack {
                    Spacer()
                    Text("Testing")
                        .foregroundColor(Color.white)
                        .frame(alignment: .leading)
                        .padding(EdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 10))
                        .shadow(radius: 5)

                    Text("1:40")
                        .foregroundColor(Color.white)
                        .frame(alignment: .leading)
                        .padding(EdgeInsets(top: 3, leading: 10, bottom: 10, trailing: 10))
                        .shadow(radius: 5)
                }
                .frame(width: 104, height: 168)
            }
        }
}

struct TestViewCollection: View {
    var collection = ["tv", "faxmachine", "printer"]
    
    var body: some View {
        ScrollView {
            HStack {
                ForEach(collection, id: \.self) { image in
                    TestView(image: image)
                        .onTapGesture {
                            print(image)
                        }
                }
            }
        }
    }
}

PlaygroundPage.current.setLiveView(TestViewCollection())

Solution

The issue is that your images are not the same aspect ratio as the frame you have put them in, so they are overflowing the frame. The solution is pretty simple. Instead of using .clipped() which just clips what you can see, use .contentShape() which will will provide an area that the .tapGesture() will use as its tappable area. Like this:

Image(systemName: image)
    .resizable()
    .aspectRatio(contentMode: .fill)
    .frame(width: 104, height: 168)
    .cornerRadius(8)
    .contentShape(Rectangle())

Answered By – Yrb

Answer Checked By – Senaida (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published.