SwiftUI Horizontal ScrollView onTapGesture 关闭
SwiftUI Horizontal ScrollView onTapGesture is Off
我在 Horizontal 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())
我在 Horizontal 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())