实现类SwiftUI原生导航侧滑动画时动画执行异常问题求助
问题根因
- 未绑定值的隐式动画触发逻辑不可控,且动画触发时视图可能尚未完成插入流程,没有可动画的初始状态,导致前几次操作无过渡效果
- 当
route为nil时,destination视图会被完全移出视图树,下次push时新创建的视图初始offset属性未被动画系统记录,首次状态变更不会触发动画 - 动画曲线选型不符合导航交互逻辑,
easeIn仅开头缓动,pop操作时表现会出现突兀感
修复方案
修改核心逻辑
- 替换隐式动画为绑定
route值的限定触发动画,确保仅route变化时触发offset动画 - 调整destination的视图生命周期逻辑,避免频繁从视图树增删,保留稳定的属性初始值
- 替换动画曲线为
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
相关产品推荐
相关产品推荐

