List reload animation glitches

|▌冷眼眸甩不掉的悲伤 提交于 2020-04-05 05:08:59

问题


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 section which looks ugly. Is there an error in my code or is this an expected SwiftUI behavior? Thanks.

import SwiftUI

struct ContentView: View {

    @ObservedObject var viewModel = ViewModel(photoLibraryService: PhotoLibraryService.shared)

    var body: some View {
        NavigationView {
            List {
                Section {
                    TextField("Enter Album Name", text: $viewModel.searchText)
                }
                Section {
                    if viewModel.libraryAlbums.count > 0 {
                        ForEach(viewModel.libraryAlbums) { libraryAlbum -> Text in
                            let title = libraryAlbum.assetCollection.localizedTitle ?? "Album"
                            return Text(title)
                        }
                    }
                }
            }.listStyle(GroupedListStyle())
                .navigationBarTitle(
                    Text("Albums")
                ).navigationBarItems(trailing: Button("Add Album", action: {
                        PhotoLibraryService.shared.createAlbum(withTitle: "New Album \(Int.random(in: 1...100))")
                }))
        }.animation(.default)
    }
}

回答1:


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



来源:https://stackoverflow.com/questions/59602045/list-reload-animation-glitches

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!