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

SwiftUI中如何触发一个视图的按钮并带动另一个视图的对象动画?

SwiftUI卡片按钮触发动画失效问题解决

我正在实现动画逻辑,目标是点击按钮时让卡片滑走,但当前使用@State和Binding的方案没有效果,推测问题在于卡片视图未感知到按钮的状态触发。

按钮代码

Button(action: {
    // Handle button action
    // isTapped.toggle()
    isFLipped.toggle()
}) {
    Text("👍")
        .frame(width: 70, height: 50)
        .background(Color("Easy"))
        .clipShape(RoundedRectangle(cornerRadius: 8))
}

SingleCardView代码

ZStack {
    RoundedRectangle(cornerRadius: 25, style: .continuous)
        .fill(Color.white)
        .overlay(RoundedRectangle(cornerRadius: 25).stroke(getColor(), lineWidth: 2))// 根据滑动方向改变边框颜色
        .shadow(radius: 3)

    VStack {
        NavigationStack {
            Text(card.term ?? "Unnamed Card")
            Divider()
            if isTapped {
                Text(card.definition ?? "Unnamed Card")
            }
        }
    }
}
.frame(width: 300, height: 500)
.rotation3DEffect(
    Angle(degrees: isFLipped ? 360: 0),
    axis: (x: 0, y: isFLipped ? 360 : 0, z: 0)
)
.onTapGesture {
    isTapped.toggle()
}

核心问题与修复步骤

问题根源是按钮所在视图的isFLipped状态和SingleCardView的状态是独立的两个变量,必须通过@Binding将父视图的状态传递给子视图,才能实现状态同步。

  1. 修改SingleCardView,将内部的isFLipped改为@Binding:
struct SingleCardView: View {
    let card: Card // 替换为你的卡片数据模型
    @Binding var isFLipped: Bool
    @State private var isTapped = false
    
    // 保留你原有的getColor()实现
    func getColor() -> Color {
        // 你的颜色逻辑
        return .gray
    }
    
    var body: some View {
        // 原有视图结构保持不变
        ZStack {
            RoundedRectangle(cornerRadius: 25, style: .continuous)
                .fill(Color.white)
                .overlay(RoundedRectangle(cornerRadius: 25).stroke(getColor(), lineWidth: 2))
                .shadow(radius: 3)

            VStack {
                NavigationStack {
                    Text(card.term ?? "Unnamed Card")
                    Divider()
                    if isTapped {
                        Text(card.definition ?? "Unnamed Card")
                    }
                }
            }
        }
        .frame(width: 300, height: 500)
        .rotation3DEffect(
            Angle(degrees: isFLipped ? 360: 0),
            axis: (x: 0, y: isFLipped ? 360 : 0, z: 0)
        )
        .onTapGesture {
            isTapped.toggle()
        }
    }
}
  1. 在父视图中,将@State修饰的isFLipped通过绑定传递给SingleCardView:
struct ParentView: View {
    @State private var isFLipped = false
    let card: Card // 你的卡片数据
    
    var body: some View {
        VStack {
            // 使用$传递绑定
            SingleCardView(card: card, isFLipped: $isFLipped)
            
            Button(action: {
                isFLipped.toggle()
            }) {
                Text("👍")
                    .frame(width: 70, height: 50)
                    .background(Color("Easy"))
                    .clipShape(RoundedRectangle(cornerRadius: 8))
            }
        }
    }
}

实现"滑走"动画(可选)

如果你的需求是卡片滑出屏幕而非旋转,可将rotation3DEffect替换为以下动画:

.offset(x: isFLipped ? UIScreen.main.bounds.width : 0)
.opacity(isFLipped ? 0 : 1)
.animation(.easeInOut(duration: 0.5), value: isFLipped)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 21:50:28