即使没有“点击”,SwiftUI List ForEach 视图中的按钮也会触发?
Posted
技术标签:
【中文标题】即使没有“点击”,SwiftUI List ForEach 视图中的按钮也会触发?【英文标题】:Buttons in SwiftUI List ForEach view trigger even when not "tapped"? 【发布时间】:2022-01-20 18:30:39 【问题描述】:我有以下代码:
struct ButtonTapTest: View
let items = [1, 2, 3]
var body: some View
List
ForEach(items, id:\.self) item in
CellTestView()
struct CellTestView:View
var body: some View
VStack
Button
print("TOP")
label:
Image(systemName: "play.fill")
.font(.system(size: 40))
.foregroundColor(.red)
.border(.red)
Spacer()
Button
print("BOTTOM")
label:
Image(systemName: "play")
.font(.system(size: 40))
.foregroundColor(.red)
.border(.yellow)
创建以下屏幕:
问题:
无论我在哪里点击CellTestView
,都会在单元格中触发两个按钮操作。我希望单独触发各个按钮操作,每个按钮仅在其按钮被点击时触发,而不是在我在单元格的其他任何地方点击外部时触发。
您可以在下面的 gif 中看到,无论我在哪里点击 CellTestView
,这两个按钮操作都会触发,无论我点击视图的哪个位置,“TOP”和“BOTTOM”日志都会在同一时间。
如何解决此问题,以便单元格中的两个按钮独立接收点击,并且仅当点击位于相关按钮内时?
【问题讨论】:
【参考方案1】:当列表行中有多个按钮时,您需要手动将按钮样式设置为.borderless
或.plain
。这是因为按钮“适应”它们的上下文。
根据documentation:
如果您在容器内创建按钮,如List,则样式将解析为该容器内针对该特定平台的按钮的推荐样式。
因此,当您的按钮位于列表中时,它的点击目标会延伸以填充行,并且您会获得高亮动画。当你有两个以上的按钮时,SwiftUI 不够聪明,无法阻止这种副作用,所以你需要手动设置buttonStyle
。
CellTestView()
.buttonStyle(.borderless)
结果:
【讨论】:
那么,这是为什么呢?我想了解这样做的原因。我们是否需要一直使用.buttonStyle(.borderless)
修饰符来修改单元格视图以使按钮工作,或者这是一个例外?你能详细说明为什么会这样吗?
@zumzum 查看我的编辑【参考方案2】:
我对这个问题的解决方法是将每个按钮包装在它自己的 VStack 或 HStack 中。
【讨论】:
【参考方案3】:当您有一个列表时,点击列表行将触发两个按钮。 试试这段代码,让每个“按钮”等效,分别触发。
struct CellTestView: View
var body: some View
VStack
Image(systemName: "play.fill") .font(.system(size: 40)).foregroundColor(.red).border(.red)
.onTapGesture
print("-----> playFill \(playFill)")
Spacer()
Image(systemName: "play") .font(.system(size: 40)).foregroundColor(.red).border(.yellow)
.onTapGesture
print("--> play \(play)")
【讨论】:
以上是关于即使没有“点击”,SwiftUI List ForEach 视图中的按钮也会触发?的主要内容,如果未能解决你的问题,请参考以下文章
iOS 15.3+ SwiftUI的Form视图中嵌入List及Button若干诡异行为的解决
Xcode 12 + SwiftUI List:点击粘贴时列表行叠加
使用 SwiftUI,我们在 List 中安装了一个 Button。为啥当我点击按钮显示模态然后再次关闭时模态消失?
为啥即使发布者发出一个值,我的视图也没有在 SwiftUI 中呈现