我追求的是一个垂直滚动视图,这是无限的双向:向上滚动到顶部或向下滚动到底部导致动态添加更多的项目。我遇到的几乎所有帮助都只关心底部的范围是无限的。我确实遇到过this relevant answer,但它不是我特别想要的(它是根据持续时间自动添加项目,需要与方向按钮交互以指定滚动方式)。less relevant answer非常有用。根据这里提出的建议,我意识到我可以随时记录可见的项目,如果它们碰巧是从顶部/底部的X个位置,在列表的开始/结束索引处插入一个项目。
另一个注意事项是,我得到的列表从中间开始,所以没有必要添加任何东西,除非你已经移动了50%的向上/向下。
需要说明的是,这是一个日历屏幕,我希望用户可以自由地滚动到任何时间。
struct TestInfinityList: View {
@State var visibleItems: Set<Int> = []
@State var items: [Int] = Array(0...20)
var body: some View {
ScrollViewReader { value in
List(items, id: \.self) { item in
VStack {
Text("Item \(item)")
}.id(item)
.onAppear {
self.visibleItems.insert(item)
/// if this is the second item on the list, then time to add with a short delay
/// another item at the top
if items[1] == item {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
withAnimation(.easeIn) {
items.insert(items.first! - 1, at: 0)
}
}
}
}
.onDisappear {
self.visibleItems.remove(item)
}
.frame(height: 300)
}
.onAppear {
value.scrollTo(10, anchor: .top)
}
}
}
}
除了一个很小但很重要的细节之外,这基本上工作得很好。当从顶部添加一个项目时,根据我向下滚动的方式,它有时会很不稳定。这在连接的夹子末端最明显。
4条答案
按热度按时间vs91vp4v1#
我试过你的代码,不能修复任何与列表或滚动视图,但它是可能的作为一个uiscrollview,无限滚动。
1.将uiscrollView Package 在UIViewRepresentable中
2.this is my whole code for the infinitly scrolling uiscrollview
仔细观察这个,它几乎是不言自明的,取自WWDC 2011的想法,当你足够接近边缘时,你将偏移量重置为屏幕中间,这一切都归结为平铺视图,以便它们都显示在彼此的顶部。如果你想对课堂有任何澄清,请在评论中提出。当你弄清楚了这两个后,你就粘上SwiftUIView,它也在提供的类中。现在,唯一的方法,为视图被看到在屏幕上是指定一个显式的大小为hosting.view,如果你弄清楚如何使SwiftUIView大小hosting.view,请告诉我在评论,我正在寻找答案。希望代码对某人有所帮助,如果有错误请留言。
8oomwypt2#
在浏览了你的代码之后,我相信你看到的这种跳跃是由以下原因引起的:
如果你把两者都去掉,只留下
items.insert(items.first! - 1, at: 0)
,跳跃就会停止。qzlgjiam3#
这两天我一直在为这个问题绞尽脑汁。。像@Ferologics建议的那样去掉DispatchQueue几乎可以工作,但是如果你拉得太用力,你会遇到无限自动滚动的潜在问题。我最终放弃了无限滚动,并使用下拉刷新SwiftUIRefresh从顶部加载新项目。它现在做的工作,但我仍然很想知道如何获得真正的无限滚动上升!
以及ViewModel:
n3h0vuf24#
对于其他仍然遇到SwiftUI这个问题的人,我的解决方法是从两个方向上的一组荒谬的月开始,显示一个
LazyVStack
,然后滚动到当前的月.onAppear
。这里明显的问题是你会得到一个令人困惑的用户体验,他们在日历跳到当前月份之前看到遥远过去的一个随机月份。我通过将整个日历隐藏在一个矩形和一个ProgressView
后面,直到.onAppear
块的末尾来处理这个问题。有一个非常小的延迟,用户看到加载动画,然后日历弹出所有准备好去和当前月份。