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

如何停止LazyVGrid全局动画?滚动时未显示元素仍抖动

问题分析

问题出在LazyVGrid的懒加载特性和手动管理动画状态的冲突上:

  • 关闭抖动开关(isShaking = false)时,可视区内的元素会通过onChange回调重置旋转角度,但未加载的元素滚动进入可视区时,其@State变量rotationAngle可能保留了复用视图的旧动画状态,或者手动启动的repeatForever动画未被正确终止,导致即使isShaking为false仍持续抖动。
  • 手动控制rotationAngle和动画的方式,无法让SwiftUI的动画系统正确跟踪状态变化,尤其在懒加载视图复用场景下容易出现状态残留。
解决方案

重构GridElementView的动画逻辑,去掉手动维护的rotationAngle状态,直接通过isShaking值控制旋转角度和动画,让SwiftUI自动处理动画的启停与视图复用的状态重置:

struct GridElementView: View {
    
    let index: String
    let isShaking: Bool
    let onDelete: () -> Void
    
    var body: some View {
        Button {
            onDelete()
        } label: {
            ZStack {
                RoundedRectangle(cornerRadius: 10)
                    .fill(Color.blue)
                    .frame(height: 250)
                
                Text("\(index)")
                    .font(.headline)
                    .foregroundColor(.white)
            }
            // 根据isShaking状态控制旋转角度
            .rotationEffect(.degrees(isShaking ? 2.5 : 0))
            // 绑定动画到isShaking,自动处理启停逻辑
            .animation(
                isShaking ? .linear(duration: 0.15).repeatForever(autoreverses: true) : .interactiveSpring(),
                value: isShaking
            )
        }
    }
}

同时移除GridElementView中未使用的ViewModel扩展,减少冗余代码。

方案生效原因
  1. 状态驱动动画:直接通过isShaking值控制旋转角度,无需手动维护rotationAngle状态,彻底避免了复用视图时的状态残留问题。
  2. 自动动画管理:animation修饰符绑定到isShaking值,当状态变化时,SwiftUI会自动启动/终止对应动画——包括懒加载视图刚进入可视区时,会直接根据当前isShaking状态应用正确的样式和动画状态。
  3. 适配懒加载特性:LazyVGrid复用视图时,新元素会继承当前isShaking状态,不会保留旧视图的动画残留。
额外优化

如果需要更平滑的停止过渡,可以将关闭时的动画类型替换为.easeOut(duration: 0.2),根据需求调整过渡效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 05:03:09