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

SwiftUI自定义过渡动画未生效,如何实现视图上下切换效果?

解决SwiftUI视图切换过渡不生效的问题

问题根源

你的代码有三个核心问题导致过渡失效:

  1. 状态变更未触发动画:show.toggle()没有包裹在withAnimation闭包中,SwiftUI无法识别需要为视图切换添加动画效果。
  2. 自定义过渡方向与需求不符:你定义的不对称过渡的插入/移除方向和预期的滑入滑出逻辑不匹配,导致动画表现不符合预期。
  3. 屏幕尺寸获取方式非SwiftUI原生:使用UIApplication获取屏幕尺寸的方式不够优雅,且在多场景下可能出现适配问题。

修正方案

1. 调整自定义过渡逻辑

根据你的需求,正确的不对称过渡应该是:

  • 红色视图(视图1):插入时从底部滑入,移除时从底部滑出
  • 蓝色视图(视图2):插入时从顶部滑入,移除时从顶部滑出

2. 用withAnimation包裹状态变更

确保每次切换show状态时,都在动画闭包中执行,强制触发过渡动画。

3. 用GeometryReader获取屏幕尺寸

替代原有的widthOrHeight函数,更符合SwiftUI的布局逻辑,适配不同设备和场景。

完整修正代码

import SwiftUI

extension AnyTransition {
    // 视图1(红色):从底部滑入,从底部滑出
    static var moveFromBottom: AnyTransition {
        .asymmetric(
            insertion: .move(edge: .bottom),
            removal: .move(edge: .bottom)
        )
    }
    // 视图2(蓝色):从顶部滑入,从顶部滑出
    static var moveFromTop: AnyTransition {
        .asymmetric(
            insertion: .move(edge: .top),
            removal: .move(edge: .top)
        )
    }
}

struct SlideTransitionView: View {
    @State private var showBlueView = true
    
    var body: some View {
        GeometryReader { geo in
            ZStack {
                if showBlueView {
                    Rectangle()
                        .fill(.blue.gradient)
                        .frame(
                            width: geo.size.width * 0.8,
                            height: geo.size.height
                        )
                        .transition(.moveFromTop)
                        .onTapGesture {
                            withAnimation {
                                showBlueView.toggle()
                            }
                        }
                } else {
                    Rectangle()
                        .fill(.red.gradient)
                        .frame(
                            width: geo.size.width * 0.8,
                            height: geo.size.height
                        )
                        .transition(.moveFromBottom)
                        .onTapGesture {
                            withAnimation {
                                showBlueView.toggle()
                            }
                        }
                }
            }
            .ignoresSafeArea()
        }
    }
}

struct SlideTransitionView_Previews: PreviewProvider {
    static var previews: some View {
        SlideTransitionView()
    }
}

代码说明

  • 过渡逻辑:点击蓝色视图时,它从顶部滑出,同时红色视图从底部滑入;点击红色视图时,它从底部滑出,蓝色视图从顶部滑入,完全匹配你的需求。
  • 动画控制:withAnimation会为视图状态变化应用默认动画,你也可以指定动画类型(比如withAnimation(.easeInOut(duration: 0.5)))来调整动画速度和曲线。
  • 布局优化:GeometryReader直接获取父视图的尺寸,避免依赖UIKit API,适配性更强。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 17:34:52