如何为 SwiftUI 列表中的各个行设置动画?

Posted

技术标签:

【中文标题】如何为 SwiftUI 列表中的各个行设置动画?【英文标题】:How can I animate individual rows in SwiftUI List? 【发布时间】:2021-09-17 12:53:19 【问题描述】:

我想显示一个列表,其中每一行都带有不透明动画并且延迟增加。所以第一行应该在 0.1 秒后出现,第二行在 0.3 秒后出现,第三行在 0.5 秒后出现,以此类推。

我尝试了以下方法,但它不起作用,因为所有行都同时出现并且没有动画。

任何提示将不胜感激!

struct GuideListView: View 

    @State var showListItems = false
    @State var animationDelay = 0.1
    // definitions of viewRouter, data etc.

    var body: some View 

        VStack 

            // other items, navLink etc.

            List 
                
                ForEach(data)  item in
                    
                    Button(action: 
                        // navigation action
                    , label: 
                        RowView(item: item)
                    )
                    .opacity(showListItems ? 1 : 0)
                    .animation(Animation.easeOut(duration: 0.6).delay(animationDelay), value: showListItems)
                    .onAppear
                        animationDelay = animationDelay + 0.2
                    

                 //: ForEach
          
             //: List

         //: VStack
        .onAppear
            showListItems = true
    

【问题讨论】:

【参考方案1】:

关键似乎是使用 ForEach 循环中的索引来设置动画出现的时间。

下面是代码。切换开关只是重置状态以显示动画:

struct GuideListView: View 
    let data = ["One", "Two", "Three", "Four"]
    @State var showListItems = false
    @State var animationDelay = 0.5
    // definitions of viewRouter, data etc.
    
    var body: some View 
        
        VStack 
            
            // other items, navLink etc.
            Toggle("Show List Items", isOn: $showListItems)

            List 
                
                ForEach(data.indices)  index in
                    
                    Button(action: 
                        // navigation action
                    , label: 
                        Text(data[index])
                    )
                        .opacity(showListItems ? 1 : 0)
                        .animation(Animation.easeOut(duration: 0.6).delay(animationDelay * Double(index)), value: showListItems)

                 //: ForEach
                
             //: List
            
         //: VStack
    

【讨论】:

感谢您的帮助。这是正确的解决方案。我又玩弄了一些,因为当使用 onAppear 而不是 Toggle() 触发时它不起作用。事实证明,onAppear 需要延迟,一切都会正常工作。更重要的是,引入延迟使我原来的解决方案也能正常工作!但是,它会同时显示所有行动画,而您的解决方案会产生所需的行为,其中行一个接一个地动画。 我错过了您原始问题中您说它们没有动画的部分。我一下子全神贯注并解决了这个问题。有时我需要更仔细地阅读。很高兴它已修复! 是的,这似乎是解决方案。不幸的是,从那以后我发现使用索引确实搞砸了数据过滤,Xcode 以我的方式抛出 BoundsFails。但这是另一个问题。目前,我坚持一次性为整个列表设置动画。 我会期待这个问题。我不确定这实际上是一个问题。这可能是事情的顺序问题。

以上是关于如何为 SwiftUI 列表中的各个行设置动画?的主要内容,如果未能解决你的问题,请参考以下文章

如何为通过 SwiftUI 中的自定义结构传递的 @State 值设置动画

SwiftUI 动画列表行的展开和折叠

如何为 Flutter SliverList 中的元素设置动画?

SwiftUI 中列表行(List Row)展开和收起无动画或动画诡异的解决

SwiftUI 中列表行(List Row)展开和收起无动画或动画诡异的解决

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