SwiftUI - 在动态过滤列表时,防止从 flying/zooming 到右侧的部分
SwiftUI - Prevent Sections from flying/zooming to the right in List when dynamically filtering them
我最初问这个问题:
在那里,我有一个 List
没有部分。我正在过滤它们,以便它只显示包含 TextField
内文本的行。解决方案是将 List
内的所有内容包装在 Section
.
中
不幸的是,我现在需要过滤 Section
s。这是我的代码:
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 = ""
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 those that contain searchText
groups.filter { group in
searchText.isEmpty || group.groupName.localizedStandardContains(searchText)
}
) { group in
Section(header: Text(group.groupName)) {
ForEach(group.people) { person in
Text(person.name)
}
}
}
}
.animation(.default) /// apply the animation
}
}
}
结果:
我在 ForEach
中传入过滤数组以确定 Section
。但是,每当该数组发生变化时, List
的动画就会非常奇怪。 Section
s zoom/fly 到右侧,当数组再次包含它们时从左侧返回。 我怎样才能避免这个动画?
如果我删除 .animation(.default)
,它根本不会像预期的那样具有动画效果。但是,我还是想要一个动画。有没有办法淡化更改或滑动更改?
解决方案是不使用列表。只要你不使用选择和行删除 ScrollView 基本上是相同的。
如果你想让它的样式有点像 List 那也不难:
struct SearchAnimationExample: View {
...
var body: some View {
VStack {
TextField("Search here", text: $searchText) /// text field
.padding()
ScrollView {
VStack(spacing: 0) {
ForEach(
groups.filter { group in
searchText.isEmpty || group.groupName.localizedStandardContains(searchText)
}
) { group in
Section(header: header(title: group.groupName)) {
ForEach(group.people) { person in
row(for: person)
Divider()
}
}
}.transition(.opacity) // Set which transition you would like
// Always full width
HStack { Spacer() }
}
}
.animation(.default)
}
}
func header(title: String) -> some View {
HStack {
Text(title).font(.headline)
Spacer()
}
.padding(.horizontal)
.background(Color.gray.opacity(0.4))
}
func row(for person: Person) -> some View {
HStack {
Text(person.name)
Spacer()
}.padding()
}
}
看起来与默认列表几乎相同:
我最初问这个问题:
在那里,我有一个 List
没有部分。我正在过滤它们,以便它只显示包含 TextField
内文本的行。解决方案是将 List
内的所有内容包装在 Section
.
不幸的是,我现在需要过滤 Section
s。这是我的代码:
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 = ""
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 those that contain searchText
groups.filter { group in
searchText.isEmpty || group.groupName.localizedStandardContains(searchText)
}
) { group in
Section(header: Text(group.groupName)) {
ForEach(group.people) { person in
Text(person.name)
}
}
}
}
.animation(.default) /// apply the animation
}
}
}
结果:
我在 ForEach
中传入过滤数组以确定 Section
。但是,每当该数组发生变化时, List
的动画就会非常奇怪。 Section
s zoom/fly 到右侧,当数组再次包含它们时从左侧返回。 我怎样才能避免这个动画?
如果我删除 .animation(.default)
,它根本不会像预期的那样具有动画效果。但是,我还是想要一个动画。有没有办法淡化更改或滑动更改?
解决方案是不使用列表。只要你不使用选择和行删除 ScrollView 基本上是相同的。
如果你想让它的样式有点像 List 那也不难:
struct SearchAnimationExample: View {
...
var body: some View {
VStack {
TextField("Search here", text: $searchText) /// text field
.padding()
ScrollView {
VStack(spacing: 0) {
ForEach(
groups.filter { group in
searchText.isEmpty || group.groupName.localizedStandardContains(searchText)
}
) { group in
Section(header: header(title: group.groupName)) {
ForEach(group.people) { person in
row(for: person)
Divider()
}
}
}.transition(.opacity) // Set which transition you would like
// Always full width
HStack { Spacer() }
}
}
.animation(.default)
}
}
func header(title: String) -> some View {
HStack {
Text(title).font(.headline)
Spacer()
}
.padding(.horizontal)
.background(Color.gray.opacity(0.4))
}
func row(for person: Person) -> some View {
HStack {
Text(person.name)
Spacer()
}.padding()
}
}
看起来与默认列表几乎相同: