首页 > 解决方案 > SwiftUI - 动态过滤时防止部分在列表中向右飞行/缩放

问题描述

我最初问了这个问题:

SwiftUI - 数据源为空时动态列表过滤动画飞到右侧

在那里,我有一个List没有部分。我正在过滤它们,以便它只显示包含文本的行TextField。解决方案是将所有内容包装ListSection.

不幸的是,我现在需要过滤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 = ""

    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
        }
    }
}

结果:

filtering sections causes them to fly away

我在 中传入一个过滤数组ForEach来确定Sections。然而,每当这个数组改变时,List动画真的很奇怪。Sections 缩放/飞到右侧,当数组再次包含它们时从左侧返回。我怎样才能避免这个动画?

如果我删除.animation(.default),它根本不会像预期的那样设置动画。但是,我还是想要动画。有没有办法淡化更改,或者滑动它们?

标签: iosswiftswiftuiswiftui-list

解决方案


解决方案不使用列表。只要您不使用选择和行删除 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()
    }
}

看起来与默认列表几乎相同:

在此处输入图像描述


推荐阅读