You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI嵌套Button点击动画问题:子Button触发父Button动画

解决SwiftUI嵌套Button触发父级样式动画的问题

问题原因

SwiftUI的事件会向上传递,点击嵌套在父Button内的子Button时,父Button会同时接收点击事件,导致其ButtonStyle中的按压动画被触发。

解决方案

方案一:给子Button添加高优先级手势

通过给子Button设置高优先级手势,确保点击子Button时事件被优先处理,不会传递到父Button。

修改子Button代码,添加.highPriorityGesture(TapGesture()):

Button {
  print("on child")
} label: {
  Text("Tap")
}
.buttonStyle(SmallButtonStyle())
.highPriorityGesture(TapGesture()) // 阻止事件向上传递

方案二:替换父Button为带手势的普通View(解决滚动问题)

如果需要更精确的控制,或者手势方案存在滚动冲突,可以将父级Button替换为普通View,手动通过@State变量控制按压状态和动画,同时处理滚动时的状态重置:

struct ContentView: View {
  let dataTypesArray = ["Item 1", "Item 2", "Item 3"]
  // 为每个行单独维护按压状态,避免复用问题
  @State private var pressedRows: Set<String> = []

  var body: some View {
    ScrollView {
      LazyVStack(spacing: 6) {
        ForEach(dataTypesArray, id: \.self) { each in
          HStack {
            Spacer()
            Text(each)
            Spacer()
            Button {
              print("on child")
            } label: {
              Text("Tap")
            }
            .buttonStyle(SmallButtonStyle())
          }
          .frame(height: 44)
          .frame(maxWidth: .infinity)
          .background(Color.pink)
          .clipShape(RoundedRectangle(cornerRadius: 14, style: .continuous))
          .opacity(pressedRows.contains(each) ? 0.8 : 1)
          .scaleEffect(pressedRows.contains(each) ? 0.95 : 1)
          .gesture(
            TapGesture()
              .onChanged { _ in
                pressedRows.insert(each)
              }
              .onEnded { _ in
                pressedRows.remove(each)
                print("on parent")
              }
          )
          // 滚动时重置按压状态,解决滚动冲突
          .simultaneousGesture(
            DragGesture(minimumDistance: 5)
              .onChanged { _ in
                pressedRows.remove(each)
              }
          )
        }
      }
      .padding(.horizontal, 8)
      .padding(.vertical, 10)
    }
  }
}

说明:用Set<String>维护每个行的按压状态,避免多个行复用同一个状态的问题;通过DragGesture在滚动开始时重置按压状态,解决手势方案的滚动冲突问题。

内容的提问来源于stack exchange,提问作者Dim Roe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 17:07:47