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

实现类SwiftUI原生导航侧滑动画时动画执行异常问题求助

问题根因

  • 未绑定值的隐式动画触发逻辑不可控,且动画触发时视图可能尚未完成插入流程,没有可动画的初始状态,导致前几次操作无过渡效果
  • 当route为nil时,destination视图会被完全移出视图树,下次push时新创建的视图初始offset属性未被动画系统记录,首次状态变更不会触发动画
  • 动画曲线选型不符合导航交互逻辑,easeIn仅开头缓动,pop操作时表现会出现突兀感

修复方案

修改核心逻辑

  1. 替换隐式动画为绑定route值的限定触发动画,确保仅route变化时触发offset动画
  2. 调整destination的视图生命周期逻辑,避免频繁从视图树增删,保留稳定的属性初始值
  3. 替换动画曲线为easeInOut,时长调整为接近系统导航的0.3秒(可按需修改)

修复后的完整RouterStore实现

public struct RouterStore<Destination, Content, Route, DestinationState>: View
where Destination: View,
      Content: View,
      Route: Hashable,
      DestinationState: Equatable {

    @Binding private var route: Route?
    private let toDestinationState: (Route) -> DestinationState?
    private let destination: (Binding<Route?>, DestinationState) -> Destination
    private let content: (Binding<Route?>) -> Content

    public init(
        route: Binding<Route?>,
        state toDestinationState: @escaping (Route) -> DestinationState?,
        @ViewBuilder content: @escaping (Binding<Route?>) -> Content,
        @ViewBuilder destination: @escaping (Binding<Route?>, DestinationState) -> Destination
    ) {
        self._route = route
        self.toDestinationState = toDestinationState
        self.destination = destination
        self.content = content
    }

    public var body: some View {
        GeometryReader { geometry in
            ZStack {
                content($route)
                // 固定保留destination容器,避免频繁增删视图
                ZStack {
                    if let _route = route, let _destinationState = toDestinationState(_route) {
                        ZStack {
                            Group {
                                if #available(iOS 15.0, *) {
                                    Color(uiColor: UIColor.systemBackground)
                                } else {
                                    Color(UIColor.systemBackground)
                                }
                            }
                            .preferredColorScheme(.light)
                            .ignoresSafeArea()
                            self.destination($route, _destinationState)
                        }
                    }
                }
                .frame(width: geometry.size.width)
                .offset(
                    x: route == nil ? geometry.size.width : 0,
                    y: 0
                )
                // 绑定动画触发源为route,仅route变化时触发动画
                .animation(animation, value: route)
            }
        }
    }

    // 调整为符合导航交互的动画参数
    private var animation: Animation = .easeInOut(duration: 0.3)
}

修改后首次push/pop就会有符合预期的侧滑动画,不会出现前几次无动画的问题,动画表现也和系统默认导航效果接近。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 03:57:06