簡體   English   中英

SwiftUI - 當數據源為空時,動態列表過濾 animation 飛到右側

[英]SwiftUI - Dynamic List filtering animation flies to right side when data source is empty

我有一個List ,它從我的people數組中獲取數據並顯示他們的姓名。

我還在過濾列表,使其僅顯示包含文本字段文本的名稱,即searchText 這是我的代碼:

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

如果沒有.animation(.default) ,它不會為更改設置動畫(如預期的那樣)。

無動畫過濾

使用.animation(.default) ,它會動畫!

用動畫過濾

但是,當人名都不包含searchText時,就會出現問題。 發生這種情況時, people.filter返回一個空數組, List就會崩潰。 例如,當我輸入“q”時,會發生這種情況:

列表向右縮放

整個列表飛到右邊,當我刪除“q”時從左邊放大。 我怎樣才能防止這種情況發生? 我正在尋找與正常過濾 animation 類似的 animation(向上滑動並消失,就像在第二個 gif 中一樣),或者只是淡出它。

編輯:iOS 13

我剛剛在 iOS 13 上進行了測試,如果我刪除.animation(.default) ,它可以完美運行!

iOS 13 上所需的動畫

但是,如果我再次添加.animation(.default) ,我會得到與 iOS 14 中相同的結果。

與 iOS 14 相同的結果

編輯:列出部分 + @mahan的答案

我的實際代碼對人員進行了分組,因此我已經使用了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
        }
    }
}

帶部分的排序列表

如果我按照@mahan 的建議將ForEach包裝在List中,則會發生這種情況:

List動畫完美,沒有奇怪的縮放 animation,但節標題失去了 styles 並且看起來像正常行。 但我認為我們正在接近!

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

更新

您可以根據需要添加任意數量的部分。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM