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

如何通过水平动画实现视图的展开与收起效果?

实现胶囊形背景展开+按钮渐显的动画效果

需求

  • 展开动画:胶囊形背景向外弹性展开,同时内部按钮渐显
  • 收起动画:点击按钮触发反向效果,胶囊收起、按钮渐隐

现有问题

尝试将按钮放入HStack并添加.animation(.spring(response: 0.4, dampingFraction: 0.75), value: animating),未实现目标效果,当前代码片段:

if showPetOptions {
    PetOptionsView()
        .transition(???)
}

胶囊展开效果示意图

解决办法

要实现这种联动动画,建议拆分背景和按钮的动画逻辑,具体实现如下:

1. 自定义PetOptionsView

把胶囊背景和按钮组分层,分别绑定状态控制动画:

struct PetOptionsView: View {
    @Binding var isOpen: Bool
    
    var body: some View {
        ZStack {
            // 胶囊背景:展开时宽度拉满,收起时缩到单个按钮宽度
            Capsule()
                .fill(Color.blue.opacity(0.1))
                .frame(width: isOpen ? 280 : 80, height: 44)
                .animation(.spring(response: 0.4, dampingFraction: 0.75), value: isOpen)
            
            // 按钮组:展开时渐显,收起时渐隐,加延迟让动画更有层次感
            HStack(spacing: 16) {
                Button("🐶 狗狗") {}
                Button("🐱 猫咪") {}
                Button("🐰 兔子") {}
            }
            .opacity(isOpen ? 1 : 0)
            .animation(.spring(response: 0.4, dampingFraction: 0.75).delay(0.1), value: isOpen)
        }
    }
}

2. 父视图控制动画状态

不用条件渲染隐藏视图,直接通过状态变量驱动动画,点击按钮切换状态:

struct ContentView: View {
    @State private var showOptions = false
    
    var body: some View {
        VStack(spacing: 50) {
            PetOptionsView(isOpen: $showOptions)
            
            Button(showOptions ? "收起选项" : "展开选项") {
                showOptions.toggle()
            }
        }
        .padding()
    }
}

关键细节

  • 背景用frame绑定状态配合弹簧动画,实现向外弹性展开的效果
  • 按钮添加延迟动画,避免和背景动画同步启动,视觉过渡更自然
  • 保持视图始终存在,通过状态控制动画,比条件渲染+transition的方式更易控制动画时序

如果一定要用transition实现,可以自定义过渡效果,但这种方式难以单独调整背景和按钮的动画节奏:

extension AnyTransition {
    static var capsuleExpand: AnyTransition {
        .asymmetric(
            insertion: .scale(scale: 0.3, anchor: .center).combined(with: .opacity),
            removal: .scale(scale: 0.3, anchor: .center).combined(with: .opacity)
        )
    }
}

使用方式:

if showPetOptions {
    PetOptionsView()
        .transition(.capsuleExpand)
        .animation(.spring(response: 0.4, dampingFraction: 0.75), value: showPetOptions)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 20:42:43