List reload animation glitches

前端 未结 1 1879
忘掉有多难
忘掉有多难 2020-12-19 19:15

So I have a list that changes when user fill in search keyword, and when there is no result, all the cells collapse and somehow they would fly over to the first sec

相关标签:
1条回答
  • 2020-12-19 19:54

    1) you have to use some debouncing to reduce the needs to refresh the list, while typing in the search field

    2) disable animation of rows

    The second is the hardest part. the trick is to force recreate some View by setting its id.

    Here is code of simple app (to be able to test this ideas)

    import SwiftUI
    import Combine
    
    class Model: ObservableObject {
        @Published var text: String = ""
        @Published var debouncedText: String = ""
        @Published var data = ["art", "audience", "association", "attitude", "ambition", "assistance", "awareness", "apartment", "artisan", "airport", "atmosphere", "actor", "army", "attention", "agreement", "application", "agency", "article", "affair", "apple", "argument", "analysis", "appearance", "assumption", "arrival", "assistant", "addition", "accident", "appointment", "advice", "ability", "alcohol", "anxiety", "ad", "activity"].map(DataRow.init)
        var filtered: [DataRow] {
            data.filter { (row) -> Bool in
                row.txt.lowercased().hasPrefix(debouncedText.lowercased())
            }
        }
    
        var id: UUID {
            UUID()
        }
    
        private var store = Set<AnyCancellable>()
        init(delay: Double) {
            $text
                .debounce(for: .seconds(delay), scheduler: RunLoop.main)
                .sink { [weak self] (s) in
                self?.debouncedText = s
            }.store(in: &store)
        }
    }
    
    struct DataRow: Identifiable {
        let id = UUID()
        let txt: String
        init(_ txt: String) {
            self.txt = txt
        }
    }
    
    struct ContentView: View {
    
        @ObservedObject var search = Model(delay: 0.5)
    
        var body: some View {
    
            NavigationView {
                VStack(alignment: .leading) {
    
                    TextField("filter", text: $search.text)
                        .padding(.vertical)
                        .padding(.horizontal)
    
                    List(search.filtered) { (e) in
                        Text(e.txt)
                    }.id(search.id)
                }.navigationBarTitle("Navigation")
            }
        }
    }
    
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    

    and i am happy with the result

    0 讨论(0)
提交回复
热议问题