SwiftUI-列表中的视图内触发的动画也不会使列表动画 [英] SwiftUI - Animations triggered inside a View that's in a list doesn't animate the list as well

查看:113
本文介绍了SwiftUI-列表中的视图内触发的动画也不会使列表动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个List,它显示两个相同类型的Views.当您点击其中一个视图时,它们会通过动画改变其高度.

I have a List that's displaying two Views of the same type. When you tap on one of the views, they change their height with an animation.

但是,嵌入到这些视图中的List并没有动画,这会导致丑陋的毛刺,因为List行的高度会立即更改,而该行中的实际视图是动态的:

However, the List those views are embedded in doesn't animate which results in an ugly glitch because the height of the List row changes instantly, while the actual view inside that row is animated:

我如何也可以使List动画?我尝试在其中添加.animation修饰符,但这没有任何作用.

How can I make the List animate as well? I tried addinga .animation modifier to it but that doesn't do anything.

我也不想将tapGesture移出视图.该视图应该是独立的,不应依赖其他视图来控制它(我认为这就是MVVM的目的)

I also don't want to move the tapGesture out of the view. The view should be self-contained and not rely on some other view to control it (I think that's what MVVM is about)

谢谢!

import SwiftUI

struct SubView: View {
    @State var change: Bool = false

    var body: some View {
        Rectangle()
            .frame(width: 200, height: change ? 300 : 200)
            .foregroundColor(Color.red)
            .onTapGesture {
                withAnimation {
                    self.change.toggle()
                }
        }
    }
}

struct Test: View {

    var body: some View {
        List {
            SubView()
            SubView()
        }
    }
}

struct Test_Previews: PreviewProvider {
    static var previews: some View {
        Test()
    }
}

推荐答案

解决方案就是通过为此提供显式的可动画修改器,使高度连续可动画化.

The solution is just to make height animatable continuously, by providing explicit animatable modifier for this.

这是可行的方法.在Xcode 11.4/iOS 13.4上进行了测试.

Here is working approach. Tested with Xcode 11.4 / iOS 13.4.

简单辅助修饰符的实现

struct AnimatingCellHeight: AnimatableModifier {
    var height: CGFloat = 0

    var animatableData: CGFloat {
        get { height }
        set { height = newValue }
    }

    func body(content: Content) -> some View {
        content.frame(height: height)
    }
}

使用视图进行了修改(其他部分未更改)

Modified using view (other parts unchanged)

struct SubView: View {
    @State var change: Bool = false

    var body: some View {
        Rectangle()
            .frame(width: 200)
            .modifier(AnimatingCellHeight(height: change ? 300 : 200))
            .foregroundColor(Color.red)
            .onTapGesture {
                withAnimation {
                    self.change.toggle()
                }
            }
    }
}

这篇关于SwiftUI-列表中的视图内触发的动画也不会使列表动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆