我已经在SwiftUI中实现了一个带有搜索栏的List。现在我想为这个List实现分页。当用户滚动到列表的底部时,新元素应该被加载。我的问题是,我如何检测到用户滚动到了底部?当这种情况发生时,我想加载新元素,追加它们并向用户显示它们。
我的代码如下所示:
import Foundation
import SwiftUI
struct MyList: View {
@EnvironmentObject var webService: GetRequestsWebService
@ObservedObject var viewModelMyList: MyListViewModel
@State private var query = ""
var body: some View {
let binding = Binding<String>(
get: { self.query },
set: { self.query = $0; self.textFieldChanged($0) }
)
return NavigationView {
// how to detect here when end of the list is reached by scrolling?
List {
// searchbar here inside the list element
TextField("Search...", text: binding) {
self.fetchResults()
}
ForEach(viewModelMyList.items, id: \.id) { item in
MyRow(itemToProcess: item)
}
}
.navigationBarTitle("Title")
}.onAppear(perform: fetchResults)
}
private func textFieldChanged(_ text: String) {
text.isEmpty ? viewModelMyList.fetchResultsThrottelt(for: nil) : viewModelMyList.fetchResultsThrottelt(for: text)
}
private func fetchResults() {
query.isEmpty ? viewModelMyList.fetchResults(for: nil) : viewModelMyList.fetchResults(for: query)
}
}
这种情况也有点特殊,因为列表包含搜索栏。我会感谢任何建议,因为有了这个:)。
3条答案
按热度按时间epggiuax1#
由于您已经有了一个
List
,它带有一个用于搜索栏的人工行,您可以简单地向列表中添加另一个视图,当它出现在屏幕上时,该列表将触发另一次获取(使用Josh建议的onAppear()
)。通过这样做,您不必进行任何“复杂”的计算来知道一行是否是最后一行...人工行总是最后一行!我已经在我的一个项目中使用了这个元素,但我从来没有在屏幕上看到过这个元素,因为加载在它出现在屏幕上之前就被触发了。(您当然可以使用透明/不可见的元素,或者甚至可以使用微调器;- ))
xsuvu9jc2#
向
MyRow
中添加一个.onAppear()
,并让它调用viewModel,然后检查它是否等于列表中的最后一项,或者它是否距离列表末尾有n项,并触发分页。bt1cpqcv3#
这个对我很有效:
您可以使用两种不同的方法为List添加分页:最后一项法和阈值项法。
这就是这个包向RandomAccessCollection添加两个函数的方式:
是最后一个项目
使用此函数检查当前List项迭代中的项是否是集合的最后一项。
是阈值项
使用此函数,您可以确定当前列表项迭代的项是否是您定义的阈值项。将偏移量(到最后一个项的距离)传递给函数,以便确定阈值项。
示例
最后一项方法:
阈值项目方法:
字符串扩展名:
Christian Elies, code reference