Swiftui 更改数据源时的快捷菜单列表动画

Swiftui 更改数据源时的快捷菜单列表动画,swiftui,Swiftui,我在我的SwiftUI应用程序中有一个列表,上面的按钮可以查看要加载到列表中的上一个/下一个类别的项目。按下按钮时,列表的源将更改,列表将更新为默认动画(行将折叠) 简化可复制版本的代码(请参见下面的屏幕截图): 导入快捷界面 结构ContentView:View{ 私人出租模型=[ [“a”、“b”、“c”、“d”、“e”、“f”], [“g”,“h”], [“i”、“j”、“k”、“l”], ] @状态私有变量selectedCategory=1 私有变量查看模型:[字符串]{ 型号[选定类

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

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

导入快捷界面
结构ContentView:View{
私人出租模型=[
[“a”、“b”、“c”、“d”、“e”、“f”],
[“g”,“h”],
[“i”、“j”、“k”、“l”],
]
@状态私有变量selectedCategory=1
私有变量查看模型:[字符串]{
型号[选定类别]
}
var body:一些观点{
VStack(间距:0.0){
HStack{
按钮(操作:上一个){
正文(“”)
}
}
列表(viewingModels,id:\.self){中的模型
文本(模型)
}
}
}
private func previous(){
如果选择类别>0{
selectedCategory-=1
}
}
私有func next(){
如果选择类别<(models.count-1){
selectedCategory+=1
}
}
}


现在,我不想在这里使用默认列表动画。我希望列表项水平滑动。因此,当您按
箭头查看下一类项目时,屏幕上的现有项目应移到左侧,新项目应从右侧进入。如果您的按钮按照您的建议进行了包装,并且我添加了一个简单的方向布尔值,则当您按下
时,情况正好相反:

Button(action: {
            withAnimation {
                slideRight = true
                self.previous()
            }
        }) {
          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,请参阅本文:

更新:

我想提供完整的代码,并根据下面的注释删除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)
    }
}
导入快捷界面
结构ContentView:View{
私人出租模型=[
[“a”、“b”、“c”、“d”、“e”、“f”],
[“g”,“h”],
[“i”、“j”、“k”、“l”],
]
@状态私有变量selectedCategory=0
@State private var slideRight=true
私有变量查看模型:[字符串]{
型号[选定类别]
}
var body:一些观点{
VStack(间距:0.0){
HStack{
按钮(操作:{
动画片{
如果(self.selectedCategory-1<0){self.selectedCategory=self.models.count-1}
else{self.selectedCategory-=1}
self.slideRight=true
}
}) {
图像(系统名称:“箭头左”)
}
文本(“\(selectedCategory+1)”)
按钮(操作:{
动画片{
如果(self.selectedCategory+1>self.models.count-1){self.selectedCategory=0}
else{self.selectedCategory+=1}
self.slideRight=false
}
}) {
图像(系统名称:“arrow.right”)
}
}.font(.title)
列表(viewingModels,id:\.self){中的模型
文本(模型)
}
.id(selectedCategory)
.transition(.asymetric(插入:。移动(边:slideRight?.leading:。尾随),
移除:。移动(边:滑块右?。尾随:。前导)))
}.填充(10)
}
}

遗憾的是,列表中需要
.id(UUID())
会导致一系列不同的问题。例如,当点击其中一个列表行以打开该详细视图时,该视图现在不再是“实时更新”模型。因此,在服务器上对此模型所做的更改不再实时更新。或者,当您在此列表顶部显示一个模式工作表时,它会在UUID更改后滚动到顶部。但是,通过使用每个列表的常量ID很容易修复。因此,使用每个更新列表的常量ID,它可以正常工作,对吗?对!幸运的是:)@KevinRenskers在这个例子中更准确的用法是使用“.id(selectedCategory)”,这就是我所做的,并添加了完整的例子。是的,这正是我最后在代码中使用的。很高兴您为其他遇到相同问题的人更新了示例!
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)
    }
}