SwiftUI:如何阻止子视图继承父视图的导航动画?
问题描述
我使用NavigationPath已有一段时间,发现将视图插入路径时,插入的页面没有标准导航过渡动画,因此我通过以下代码强制添加动画:
.navigationDestination(for: Int.self) { i in if i == 1 { ContentsPageView(presentedNumbers: $presentedNumbers) .animation(.easeInOut(duration: 0.3)) .transition(AnyTransition.asymmetric( insertion: .move(edge: .leading), removal: .move(edge: .trailing)) ) } else { ReaderPageView(presentedNumbers: $presentedNumbers) } }
导航过渡动画运行正常,但ContentsPageView中的列表项也开始产生动画,想知道如何阻止子视图继承该动画。
解决方案
1. 在子视图中清除继承的事务动画
直接在ContentsPageView内部修改事务,清除掉继承的动画,这样列表等子视图就不会受到外部动画影响:
struct ContentsPageView: View { @Binding var presentedNumbers: [Int] var body: some View { List { // 列表项内容 } .transaction { $0.animation = nil } } }
2. 将动画绑定到导航触发动作
不要给目标视图添加.animation修饰符,而是在触发导航跳转的代码中用withAnimation包裹路径更新操作,这样动画仅作用于导航过渡,不会渗透到页面内部:
// 触发跳转的按钮示例 Button("进入目录页") { withAnimation(.easeInOut(duration: 0.3)) { presentedNumbers.append(1) } }
对应的navigationDestination代码简化为:
.navigationDestination(for: Int.self) { i in if i == 1 { ContentsPageView(presentedNumbers: $presentedNumbers) .transition(AnyTransition.asymmetric( insertion: .move(edge: .leading), removal: .move(edge: .trailing)) ) } else { ReaderPageView(presentedNumbers: $presentedNumbers) } }
3. 限定动画的触发条件
如果必须在视图层级添加动画,使用带value参数的.animation(_:value:),只在特定条件触发动画,避免影响子视图:
ContentsPageView(presentedNumbers: $presentedNumbers) .animation(.easeInOut(duration: 0.3), value: presentedNumbers.last == 1) .transition(AnyTransition.asymmetric( insertion: .move(edge: .leading), removal: .move(edge: .trailing)) )
这样动画仅在导航到该页面的瞬间触发,不会干扰页面内部列表的正常渲染。
内容的提问来源于stack exchange,提问作者kelalaka
相关产品推荐
相关产品推荐

