[英]SwiftUI - Dynamic List filtering animation flies to right side when data source is empty
I have a List
that gets data from my people
array and displays their names.我有一个List
,它从我的people
数组中获取数据并显示他们的姓名。
I'm also filtering the list so that it only shows the names that contain the text field's text, which is searchText
.我还在过滤列表,使其仅显示包含文本字段文本的名称,即searchText
。 Here's my code:这是我的代码:
struct Person: Identifiable {
let id = UUID() /// required for the List
var name = ""
}
struct ContentView: View {
@State var searchText = ""
var people = [ /// the data source
Person(name: "Alex"),
Person(name: "Ally"),
Person(name: "Allie"),
Person(name: "Bob"),
Person(name: "Tim"),
Person(name: "Timothy")
]
var body: some View {
VStack {
TextField("Search here", text: $searchText) /// text field
.padding()
List {
ForEach(
people.filter { person in /// filter the people
searchText.isEmpty || person.name.localizedStandardContains(searchText)
}
) { person in
Text(person.name)
}
}
.animation(.default) /// add the animation
}
}
}
Without .animation(.default)
, it doesn't animate the changes (as expected).如果没有.animation(.default)
,它不会为更改设置动画(如预期的那样)。
With .animation(.default)
, it animates!使用.animation(.default)
,它会动画!
However, the problem happens when none of the people's names contain searchText
.但是,当人名都不包含searchText
时,就会出现问题。 When this happens, the people.filter
returns an empty array, and the List
freaks out.发生这种情况时, people.filter
返回一个空数组, List
就会崩溃。 For example, when I type "q", this happens:例如,当我输入“q”时,会发生这种情况:
The entire list flies to the right, and zooms back in from the left when I delete "q".整个列表飞到右边,当我删除“q”时从左边放大。 How can I prevent this from happening?我怎样才能防止这种情况发生? I'm looking for a similar animation to the normal filtering animation (sliding up and disappearing, like in the second gif), or just fading it out.我正在寻找与正常过滤 animation 类似的 animation(向上滑动并消失,就像在第二个 gif 中一样),或者只是淡出它。
I just tested on iOS 13 and if I remove .animation(.default)
, it works perfectly!我刚刚在 iOS 13 上进行了测试,如果我删除.animation(.default)
,它可以完美运行!
However, if I add .animation(.default)
again, I get the same result as in iOS 14.但是,如果我再次添加.animation(.default)
,我会得到与 iOS 14 中相同的结果。
My actual code groups the people, so I already use sections
in my List
.我的实际代码对人员进行了分组,因此我已经使用了List
中的sections
。
struct Group: Identifiable {
let id = UUID() /// required for the List
var groupName = ""
var people = [Person]()
}
struct Person: Identifiable {
let id = UUID() /// required for the List
var name = ""
}
struct ContentView: View {
@State var searchText = ""
/// groups of people
var groups = [
Group(groupName: "A People", people: [
Person(name: "Alex"),
Person(name: "Ally"),
Person(name: "Allie")
]),
Group(groupName: "B People", people: [
Person(name: "Bob")
]),
Group(groupName: "T People", people: [
Person(name: "Tim"),
Person(name: "Timothy")
])
]
var body: some View {
VStack {
TextField("Search here", text: $searchText) /// text field
.padding()
List {
ForEach(
/// Filter the groups for people that match searchText
groups.filter { group in
searchText.isEmpty || group.people.contains(where: { person in
person.name.localizedStandardContains(searchText)
})
}
) { group in
Section(header: Text(group.groupName)) {
ForEach(
/// filter the people in each group
group.people.filter { person in
searchText.isEmpty || person.name.localizedStandardContains(searchText)
}
) { person in
Text(person.name)
}
}
}
}
.animation(.default) /// add the animation
}
}
}
If I wrap the ForEach
inside the List
as @mahan suggested, this happens:如果我按照@mahan 的建议将ForEach
包装在List
中,则会发生这种情况:
The List
animates perfectly with no weird zoom animation, but the section headers lose their styles and look like normal rows. List
动画完美,没有奇怪的缩放 animation,但节标题失去了 styles 并且看起来像正常行。 But I think we're getting close!但我认为我们正在接近!
Wrap ForEach in a Section , and the issue will be fixed.将ForEach包装在Section中,问题将得到解决。
List {
Section {
ForEach(
people.filter { person in /// filter the people
searchText.isEmpty || person.name.localizedStandardContains(searchText)
}
) { person in
Text(person.name)
}
}
}
.animation(.default) /// add the animation
You can add as many sections as you wish so.您可以根据需要添加任意数量的部分。
struct Person: Identifiable {
let id = UUID() /// required for the List
var name = ""
}
struct ContentView: View {
@State var searchText = ""
var people = [ /// the data source
Person(name: "Alex"),
Person(name: "Ally"),
Person(name: "Allie"),
Person(name: "Bob"),
Person(name: "Tim"),
Person(name: "Timothy")
]
var people2 = [ /// the data source
Person(name: "John"),
Person(name: "George"),
Person(name: "Jack"),
Person(name: "Mike"),
Person(name: "Barak"),
Person(name: "Steve")
]
var body: some View {
VStack {
TextField("Search here", text: $searchText) /// text field
.padding()
List {
Section {
ForEach(
people.filter { person in /// filter the people
searchText.isEmpty || person.name.localizedStandardContains(searchText)
}
) { person in
Text(person.name)
}
}
Section {
ForEach(people2.filter { person in /// filter the people
searchText.isEmpty || person.name.localizedStandardContains(searchText)
}) { person in
Text(person.name)
}
}
}
.animation(.default) /// add the animation
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.