如何在 SwiftUI 中禁用子视图上的特定状态更改动画

Posted

技术标签:

【中文标题】如何在 SwiftUI 中禁用子视图上的特定状态更改动画【英文标题】:How can I disable animating a specific state change on a subview in SwiftUI 【发布时间】:2020-11-20 16:54:02 【问题描述】:

我的contentView包括一个视图(MapCardView)在选择地图视图(MapKitView)的注释时,从启动的可见区域(MapKitView)的注释时,部分幻灯片在地图应用中):

@State private var showAnnotationCard = false
@State private var annotation: MKAnnotation?
private let kBottomCardPosition: CGFloat = -150

var body: some View 
    
        ZStack 
            
            MapKitView(isAnnotationSelected: $showAnnotationCard, selectedAnnotation: $annotation)
                .edgesIgnoringSafeArea(.all)
        
            MapCardView(annotation: $annotation)
                .edgesIgnoringSafeArea(.bottom)
                .offset(y: (bounds.size.height + bounds.safeAreaInsets.bottom)) //Push the view off the screen on launch
                .offset(y: showAnnotationCard ? kBottomCardPosition : 0) //Push the view back into the visible area if an annotation is selected
                .animation(.spring()) //Animate the change of the offset for the "sliding" effect
                
        
    
    


struct MapCardView: View 

    @Binding var annotation: MKAnnotation?

    var body: some View 
    
        VStack 
           
            HStack 
                VStack(alignment: .leading) 
                    
                    Text((annotation?.title ?? "") ?? "")
                        .font(.title2).bold()
                    
                    Text((annotation?.subtitle ?? "") ?? "")
                        .font(.caption)
                
                
                Spacer()
                
            
            .padding(.leading)
            
            Spacer()
        
        .frame(maxWidth: .infinity)
        
    

在 MapCardView 仍然可见时在地图视图上选择不同的注释将导致文本视图(显示注释的标题和副标题)动画内容更改,如果随后的文本内容占用比前一个宽度更大。我不想看到文本更改被动画化,而是让它在没有动画的情况下立即显示。

通过在相关文本视图上使用 .animation(nil),这些视图也将停止滑动,而是立即出现和消失,这不是我们想要的行为。是否可以单独排除内容更改的动画,或者我必须完全改变我为超级视图设置动画的方式,并且对我的动画内容进行更多限制?

更新 感谢@Asperi 的回答,将动画限制为仅观察 showAnnotationCard 状态的变化确实会阻止文本在屏幕上对其宽度进行动画更改。但是,当第一次通过选择注释拉起卡片时,它仍然显示文本更改动画。

【问题讨论】:

【参考方案1】:

尝试限制状态值的动画

MapCardView(annotation: $annotation)
    .edgesIgnoringSafeArea(.bottom)
    .offset(y: (bounds.size.height + bounds.safeAreaInsets.bottom))
    .offset(y: showAnnotationCard ? kBottomCardPosition : 0)
    .animation(.spring(), value: showAnnotationCard)           // << here !!

【讨论】:

感谢@Asperi,当我在 showAnnotationCard = true 时选择注释时,它确实修复了动画更改。但是,当我第一次选择注释并向上滑动卡片时,仍然有一个变化动画。你有什么进一步的想法吗?

以上是关于如何在 SwiftUI 中禁用子视图上的特定状态更改动画的主要内容,如果未能解决你的问题,请参考以下文章

如何将 SwiftUI 状态从特定值更改为新状态值设置动画?

如何在 SwiftUI 中禁用位置动画?

如何防止 SwiftUI clipShape 影响子视图

如何在 SwiftUI 应用程序生命周期中更改特定视图的状态栏颜色?

SwiftUI 如何快速识别视图(View)界面的刷新是由哪个状态的改变导致的?

SwiftUI 如何快速识别视图(View)界面的刷新是由哪个状态的改变导致的?