更改数据源时的SwiftUI列表动画

时间:2020-01-31 18:44:39

标签: swiftui

我的SwiftUI应用程序中有一个列表,上面有个按钮,用于查看要加载到列表中的项目的上一个/下一个类别。当您按下按钮时,列表的来源将更改,并且列表将以其默认动画(其中的行被折叠)更新。

简化的可复制版本的代码(请参见下面的屏幕截图):

$name

enter image description here

现在,我不想在此处使用默认的列表动画。我希望列表项水平滑动。因此,当您按下import SwiftUI struct ContentView: View { private let models = [ ["a", "b", "c", "d", "e", "f"], ["g", "h"], ["i", "j", "k", "l"], ] @State private var selectedCategory = 1 private var viewingModels: [String] { models[selectedCategory] } var body: some View { VStack(spacing: 0.0) { HStack { Button(action: previous) { Text("<") } Text("\(selectedCategory)") Button(action: next) { Text(">") } } List(viewingModels, id: \.self) { model in Text(model) } } } private func previous() { if selectedCategory > 0 { selectedCategory -= 1 } } private func next() { if selectedCategory < (models.count - 1) { selectedCategory += 1 } } } 箭头查看下一类别的项目时,屏幕上的现有项目应移至左侧,而新项目应从右侧移入。按下>按钮时则相反。基本上,它应该看起来像是一个具有多个页面的收藏夹视图。

我已经发现用<包装previousnext函数的内容会将默认的列表动画更改为其他内容。然后,我尝试将withAnimation添加到列表(及其中的文本)以更改新的动画,但这没有效果。不确定如何更改列表的动画,尤其是对于2个不同的按钮使用不同的“单向/单向”。

在实际应用中使用按类别列出列表的ScrollView不会在实际应用中按比例缩放,尽管是的,这可能是此简单示例(行数很少)的解决方案:)

1 个答案:

答案 0 :(得分:2)

如果按您的建议包装了按钮,并且我添加了一个简单的布尔值指示:

Button(action: {
            withAnimation {
                slideRight = true
                self.previous()
            }
        }) {
          Text("<")
        }

与另一方向相反:

Button(action: {
            withAnimation {
                slideRight = false
                self.next()
            }
        }) {
          Text(">")
        }

然后您可以像这样转换视图:

List(viewingModels, id: \.self) { model in
            Text(model)
        }
        .id(UUID())
        .transition(.asymmetric(insertion: .move(edge: slideRight ? .leading : .trailing),
                                removal: .move(edge: slideRight ? .trailing : .leading)))

请注意,为了使列表不具有动画效果,我们需要每次为列表指定一个新的唯一ID,请参阅本文:https://swiftui-lab.com/swiftui-id/

更新:

我想提供完整的简化代码,并根据以下评论删除了UUID()用法。

import SwiftUI

struct ContentView: View {
    private let models = [
        ["a", "b", "c", "d", "e", "f"],
        ["g", "h"],
        ["i", "j", "k", "l"],
    ]

    @State private var selectedCategory = 0
    @State private var slideRight = true

    private var viewingModels: [String] {
        models[selectedCategory]
    }

    var body: some View {
        VStack(spacing: 0.0) {
            HStack {
                Button(action: {
                    withAnimation {
                        if(self.selectedCategory - 1 < 0) { self.selectedCategory = self.models.count - 1 }
                            else {  self.selectedCategory -= 1 }
                        self.slideRight = true
                    }
                }) {
                    Image(systemName: "arrow.left")
                }

                Text("\(selectedCategory + 1)")

                Button(action: {
                    withAnimation {

                        if(self.selectedCategory + 1 > self.models.count - 1) { self.selectedCategory = 0 }
                            else { self.selectedCategory += 1 }
                        self.slideRight = false
                    }
                }) {
                    Image(systemName: "arrow.right")
                }
            }.font(.title)

            List(viewingModels, id: \.self) { model in
                Text(model)
            }
            .id(selectedCategory)
            .transition(.asymmetric(insertion: .move(edge: slideRight ? .leading : .trailing),
                                    removal: .move(edge: slideRight ? .trailing : .leading)))
        }.padding(10)
    }
}

animated list change