SwiftUI Horizo​​ntal ScrollView onTapGesture 关闭

SwiftUI Horizontal ScrollView onTapGesture is Off

我在 Horizo​​ntal ScrollView 中遇到了一些非常奇怪的行为,似乎单元格的可点击框架发生了偏移。例如,如果您单击第一个单元格的左半部分,它将注册第一个单元格的点击,但如果您单击第一个单元格的右半部分,它将注册第二个单元格的点击。我不确定为什么会这样。

我已经包含了下面的代码,您可以将此代码复制并粘贴到 playground 中以重现该问题。有什么想法吗?

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())

问题是:

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

更改 .aspectRatio(contentMode: .fill)。 -> 进入 .fit

如果你像这样移动 .clipped() :

Image(systemName: image)
   .resizable()
   .aspectRatio(contentMode: .fill)
   .clipped()
   .frame(width: 104, height: 168)

您将看到:

这就是发生的原因。

问题是您的图片与放入它们的框架的纵横比不同,因此它们溢出了框架。解决方案非常简单。不要使用 .clipped() 来剪辑您可以看到的内容,而是使用 .contentShape() 它将提供一个区域,.tapGesture() 将用作其可点击区域。像这样:

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