如何在 SwiftUI 中使视图的高度从 0 动画到高度?

Posted

技术标签:

【中文标题】如何在 SwiftUI 中使视图的高度从 0 动画到高度?【英文标题】:How to make a view's height animate from 0 to height in SwiftUI? 【发布时间】:2021-01-06 01:25:53 【问题描述】:

我想让这个条形图的高度(较大条形图的一部分)在从 0 到其给定高度的动画上显示,但我在 SwiftUI 中无法完全弄清楚?我发现这段代码很有帮助,但只有第一条(共 7 个)动画:

struct BarChartItem: View 
    
    var value: Int
    var dayText: String
    var topOfSCaleColorIsRed: Bool
    
    @State var growMore: CGFloat = 0
    @State var showMore: Double = 0
    
    var body: some View 
        VStack 
            Text("\(value)%")
                .font(Font.footnote.monospacedDigit())
            RoundedRectangle(cornerRadius: 5.0)
                .fill(getBarColor())
                .frame(width: 40, height: growMore)
                .onAppear 
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) 
                        withAnimation(.linear(duration: 7.0)) 
                            growMore = CGFloat(value)
                            showMore = 1
                        
                    
                .opacity(showMore)
            Text(dayText.uppercased())
                .font(.caption)
            
            
        
        
    

这是图表:

 HStack(alignment: .bottom) 
                    ForEach(pastRecoveryScoreObjects)  pastRecoveryScoreObject in
                        BarChartItem(value: pastRecoveryScoreObject.recoveryScore, dayText: "\(pastRecoveryScoreObject.date.weekdayName)", topOfSCaleColorIsRed: false)
                    
                

【问题讨论】:

你其他酒吧的代码是什么? @aheze 请在底部查看我的补充 【参考方案1】:

这很有效:您可以获取 ForEach 循环的索引并将每个条形的动画延迟一段时间 * 该索引。所有的条都通过绑定连接到同一个状态变量,并且状态在出现时立即设置。您可以根据自己的喜好调整参数。

struct TestChartAnimationView: View 
    let values = [200, 120, 120, 90, 10, 80]
    @State var open = false
    
    var animationTime: Double = 0.25
    
    var body: some View 
        VStack 
            Spacer()
            HStack(alignment: .bottom) 
                ForEach(values.indices, id: \.self)  index in
                    BarChartItem(open: $open, value: values[index])
                        .animation(
                            Animation.linear(duration: animationTime).delay(animationTime * Double(index))
                        )
                
            
        
        .onAppear 
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) 
                open = true
            
        
    


struct BarChartItem: View 
    @Binding var open: Bool
    var value: Int
    
    var body: some View 
        VStack 
            Text("\(value)%")
                .font(Font.footnote.monospacedDigit())
            RoundedRectangle(cornerRadius: 5.0)
                .fill(Color.blue)
                .frame(width: 20, height: open ? CGFloat(value) : 0)
            Text("Week".uppercased())
                .font(.caption)
        
    

【讨论】:

谢谢!这很好用,除了视图是自上而下构建的,有没有办法让它们自下而上增长? 当我运行它时,它们是从下到上的,因为我把它们放在一个带有垫片的 vstack 中。如果您想要相反的方向,请尝试移动下面的垫片 ? 我确实尝试过在任一侧使用 vstack 和 spacer 但结果相同,无法弄清楚为什么它的行为会有所不同,因为我们的代码似乎相同?‍♂️【参考方案2】:

编辑:ForEach 动画有点奇怪。我不知道为什么,但这有效:

struct ContentView: View 
    let values = [200, 120, 120, 90, 10, 80]
    var body: some View 
        HStack(alignment: .bottom) 
            ForEach(values, id: \.self)  value in
                BarChartItem(totalValue: value)
                    .animation(.linear(duration: 3))
            
        
    

struct BarChartItem: View 
    @State var value: Int = 0
    var totalValue = 0
    
    var body: some View 
        VStack 
            Text("\(value)%")
                .font(Font.footnote.monospacedDigit())
            RoundedRectangle(cornerRadius: 5.0)
                .fill(Color.blue)
                .frame(width: 20, height: CGFloat(value))
            Text("Week".uppercased())
                .font(.caption)
            
        .onAppear 
            value = totalValue
        
    

我没有在onAppear 中应用动画,而是在ForEach 中应用了一个隐式动画。

结果:

【讨论】:

谢谢,但我正在尝试显示动画,以便图表中的每个条从屏幕底部依次动画到顶部。 对不起,如果我不清楚,很难说清楚,但可以想象出现的图形,从底部开始,第一个条将增长到它的高度,然后是下一个条,直到所有条都增长到他们的身高。与其从中间开始然后向上和向下增长(就像在你的动画中那样),它们应该从最底部开始并且只会向上增长。 啊,也有点像一本吧? @bze12 的回答可能有效

以上是关于如何在 SwiftUI 中使视图的高度从 0 动画到高度?的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI中应用Hero动画(Hero Animation)时一些需要填的坑

SwiftUI中应用Hero动画(Hero Animation)时一些需要填的坑

SwiftUI - 在列表中的视图内触发的动画也不会为列表设置动画

如何防止工作表在 SwiftUI 中使其后面的视图变暗或删除不必要的填充?

如何在 SwiftUI 中使整个列表行成为 NavigationLink

SwiftUI - 如何从不同的视图中获取 GeometryReader 的大小/高度?