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

SwiftUI中如何为视图过渡与修饰器设置不同动画

解决方案

要实现位置移动用2秒慢速动画,视图进出(显示/隐藏)用0.5秒快速动画,可以通过环境动画覆盖全局动画的方式区分两种场景,无需显式withAnimation:

核心思路

  • 全局隐式动画负责控制布局变化(方块上下移动)的慢速效果;
  • 给需要过渡的视图容器单独设置环境动画,覆盖全局配置,专门控制视图插入/移除(显示/隐藏)的快速过渡效果。

修改后的代码

enum Pos: Int, CaseIterable {
    case up = 0, down, none
    /// 随机返回与当前不同的状态
    var newValue: Pos { Pos(rawValue: (rawValue+Int.random(in: 1...2)) % 3)!}
}

struct ContentView: View {
    @State private var posArray: [Pos] = Array(repeating: Pos.none, count: 8).map{$0.newValue}

    var body: some View {
        VStack {
            HStack(spacing: 1) {
                ForEach(0 ..< posArray.count, id: \.self) { i in
                    VStack(spacing: 0) {
                        // 顶部占位块
                        if posArray[i] != .up { Color.clear.frame(width: 40, height: 40) }

                        // 可显示/隐藏的数字方块
                        Group {
                            if posArray[i] != .none {
                                Color.primary
                                    .frame(width: 40, height: 40)
                                    .overlay {
                                        Text((i+1).formatted())
                                            .foregroundStyle(.background)
                                    }
                            }
                        }
                        .transition(.move(edge: posArray[i] == .up ? .top : .bottom)
                            .combined(with: .opacity))
                        // 给过渡视图设置环境动画,覆盖全局配置
                        .environment(\.animation, .easeOut(duration: 0.5))

                        // 底部占位块
                        if posArray[i] != .down {Color.clear.frame(width: 40, height: 40) }
                    }
                }
            }.padding(4).border(Color.green, width: 2)

            Button("Animate Change") {
                posArray = posArray.map{ $0.newValue }
            }
        }.padding(20)
        // 全局动画控制布局移动的慢速效果
        .animation(.easeOut(duration: 2), value: posArray)
    }
}

效果说明

  1. 位置移动(比如从.up切换到.down):由于是占位块的显示/隐藏导致布局变化,受全局.animation(.easeOut(duration: 2))控制,动画时长2秒;
  2. 视图显示/隐藏(比如从.none切换到.up,或从.down切换到.none):视图的插入/移除由Group上的环境动画控制,过渡效果(移动+透明度)时长0.5秒;
  3. 完全基于隐式动画,无需在按钮点击时使用withAnimation,适配复杂场景需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 23:12:43