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

SwiftUI中使用PhaseAnimator实现Sheet弹出视图抖动效果的技术咨询

SwiftUI中使用PhaseAnimator实现Sheet弹出视图抖动效果的技术咨询

嘿,我看你正在尝试用SwiftUI的PhaseAnimator来实现动画效果,不过你贴的代码好像没写完,先帮你把完整的代码补全,再聊聊怎么调整成Sheet的抖动效果~

首先,先把你提供的不完整代码补全,让它能正常运行:

import SwiftUI  

struct CustomAnimation: ViewModifier {      
    @State private var isAnimated: Bool = false      
    
    func body(content: Content) -> some View {         
        content             
            .phaseAnimator([true, false], trigger: isAnimated) { view, phase in                 
                view                     
                    .scaleEffect(phase ? 1 : 1.2)             
            }
            .onTapGesture {                 
                isAnimated.toggle()             
            }
    }
}

// 给View加个扩展方便调用
extension View {
    func customScaleAnimation() -> some View {
        self.modifier(CustomAnimation())
    }
}

不过你要的是Sheet的抖动效果,缩放可能不太贴合需求——抖动一般是左右小幅度偏移的循环动画,我们可以把scaleEffect改成offset,调整PhaseAnimator的阶段值来模拟自然的抖动:

struct SheetShakeAnimation: ViewModifier {
    @State private var isShaking: Bool = false
    
    func body(content: Content) -> some View {
        content
            // 用偏移值数组模拟抖动的左右位移路径
            .phaseAnimator([0, 5, -5, 5, 0], trigger: isShaking) { view, offset in
                view.offset(x: offset)
            } animation: { _ in
                // 调整动画时长,让抖动更接近真实的反馈感
                .easeInOut(duration: 0.1)
            }
            .onTapGesture {
                isShaking.toggle()
            }
    }
}

// 扩展方法方便全局调用
extension View {
    func sheetShakeAnimation() -> some View {
        self.modifier(SheetShakeAnimation())
    }
}

接下来你就可以直接在Sheet视图上应用这个Modifier了,示例代码如下:

struct ContentView: View {
    @State private var showSheet = false
    
    var body: some View {
        Button("弹出Sheet") {
            showSheet.toggle()
        }
        .sheet(isPresented: $showSheet) {
            Text("这是我的Sheet视图")
                .sheetShakeAnimation() // 应用抖动动画
                .padding()
                .background(.white)
                .cornerRadius(16)
        }
    }
}

要是你想让Sheet在弹出时自动触发抖动,而不是点击触发,可以把Modifier改成监听Sheet的展示状态,调整后的代码如下:

struct AutoShakeSheetAnimation: ViewModifier {
    let isPresented: Bool
    
    func body(content: Content) -> some View {
        content
            .phaseAnimator([0, 5, -5, 5, 0], trigger: isPresented) { view, offset in
                view.offset(x: offset)
            } animation: { _ in
                .easeInOut(duration: 0.1)
            }
    }
}

extension View {
    func autoShakeWhenPresented(isPresented: Bool) -> some View {
        self.modifier(AutoShakeSheetAnimation(isPresented: isPresented))
    }
}

在Sheet上调用的方式也很简单:

.sheet(isPresented: $showSheet) {
    Text("弹出时自动抖动的Sheet")
        .autoShakeWhenPresented(isPresented: showSheet)
        .padding()
        .background(.white)
        .cornerRadius(16)
}

这样Sheet弹出来的时候就会自动完成一次抖动啦~

备注:内容来源于stack exchange,提问作者Damien

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 16:34:41