SwiftUI onAppear:动画持续时间被忽略

Posted

技术标签:

【中文标题】SwiftUI onAppear:动画持续时间被忽略【英文标题】:SwiftUI onAppear: Animation duration is ignored 【发布时间】:2021-05-26 12:34:56 【问题描述】:

我发现,如果 MyLines 视图出现在应用程序的 ContentView(根视图)中,或者它作为导航链接的目的地出现,那么 animate path stroke drawing in SwiftUI 的修剪动画会按预期工作。但是,如果视图出现在自定义视图中,SwiftUI 似乎会忽略动画持续时间——我创建了一个从右侧过渡的覆盖视图。 我只以那条线修剪动画为例——这个错误(如果有的话)似乎也出现在其他动画中,例如一些视图会在出现时改变其高度。

我尝试更改持续时间。如果我把它加倍(例如从 2 秒到 4 秒),实际的动画持续时间似乎没有改变......

结构内容视图:查看

@State var showOverlay: Bool = false

var body: some View 
    NavigationView 
        VStack 
            NavigationLink("My Lines (Nav Link)", destination: MyLines(height: 200, width: 250))
            
            Button(action: 
                self.showOverlay.toggle()
            , label: 
                Text("My Lines (overlay)")
            )
        
        
    .overlayView(content: 
        VStack 
            HStack
                Button(action:  self.showOverlay = false, label: 
                    Text("Back")
                )
                Spacer()
            .padding(.top, 40).padding(.horizontal, 15)
            
            MyLines(height: 200, width: 250)
             
            Spacer()
        
     
    , background: 
        Color(.systemBackground)
    , show: $showOverlay, size: nil, transition: AnyTransition.move(edge: .trailing).animation(.easeInOut(duration: 0.3)))


这里又是MyLine的代码——我特意将动画延迟了1秒,以便清楚问题不是由Line view所在的overlay view的过渡过长引起的。

导入 SwiftUI

结构 MyLines:查看 变量高度:CGFloat 变量宽度:CGFloat

@State private var percentage: CGFloat = .zero
var body: some View 

        Path  path in
            path.move(to: CGPoint(x: 0, y: height/2))
            path.addLine(to: CGPoint(x: width/2, y: height))
            path.addLine(to: CGPoint(x: width, y: 0))
        
        .trim(from: 0, to: percentage) // << breaks path by parts, animatable
        .stroke(Color.black, style: StrokeStyle(lineWidth: 5, lineCap: .round, lineJoin: .round))
        .onAppear 
            DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: 
                withAnimation(.easeOut(duration: 2.0)) 
                    self.percentage = 1.0
                
            )

        .padding()

   

我在这里建立了一个完整的项目来说明问题并且还包括覆盖视图: https://github.com/DominikButz/TrimAnimationBug

顺便说一句,这个持续时间问题在移除 NavigationView 后并没有消失,只使用了覆盖视图。

您可能想知道,为什么要使用自定义叠加层而不是样板导航?我发现NavigationView会导致很多问题:

很难改变背景颜色 不支持自定义转换,例如具有匹配的几何效果(我创建的叠加视图可以出现任何类型的过渡) 导致奇怪的崩溃(例如与matchedGeometryEffect相关) 阻止 .hideStatusBar 修饰符正常工作 等等等等。

【问题讨论】:

【参考方案1】:

抱歉,刚刚找到罪魁祸首。我在叠加视图上留下了一个动画(.spring())修饰符。这似乎以某种方式混淆了 SwiftUI。删除修饰符后,它按预期工作。似乎有助于写下问题以更轻松地查看解决方案...

【讨论】:

我遇到了问题。但尝试用弹簧动画修复:) 通过删除动画修改器更新了示例项目。它现在按预期工作。

以上是关于SwiftUI onAppear:动画持续时间被忽略的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI动画RoundedRectangle的宽度从0到宽度onAppear?

你可以在消失时为 SwiftUI 视图设置动画吗?

如何阻止视图在 SwiftUI 中出现动画?

SwiftUI 视图层次结构中较高的动画覆盖嵌套动画

SwiftUI:onAppear 的奇怪行为

在 SwiftUI 中动态更改动画的持续时间