SwiftUI-列表中的视图内触发的动画也不会使列表动画

时间:2019-09-09 12:52:15

标签: ios swift swiftui

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

但是,嵌入到这些视图中的List不能进行动画处理,这会导致难看的毛刺,因为List行的高度会立即更改,而该行中的实际视图是动态的:

enter image description here

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

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

谢谢!

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()
    }
}

1 个答案:

答案 0 :(得分:7)

解决方案是通过为此提供明确的可动画修改器,使高度连续可动画化。

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

demo

简单辅助修饰符的实现

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)
    }
}

使用视图修改(其他部分不变)

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()
                }
            }
    }
}