提问人:Milen Pivchev 提问时间:11/16/2023 最后编辑:Milen Pivchev 更新时间:11/16/2023 访问量:37
添加新项目时如何保持 ScrollView+LazyVStack 滚动位置
How to keep ScrollView+LazyVStack scroll position when adding new items
问:
我有以下观点:
struct NCMediaScrollView: View, Equatable {
static func == (lhs: NCMediaScrollView, rhs: NCMediaScrollView) -> Bool {
return lhs.metadatas == rhs.metadatas
}
@Binding var metadatas: [tableMetadata]
@Binding var isInSelectMode: Bool
@Binding var selectedMetadatas: [tableMetadata]
@Binding var columnCountStages: [Int]
@Binding var columnCountStagesIndex: Int
@Binding var title: String
@State private var dataID: String?
let queuer: Queuer
let onCellSelected: (ScaledThumbnail, Bool) -> Void
let onCellContextMenuItemSelected: (ScaledThumbnail, ContextMenuSelection) -> Void
let onRefresh: () async -> Void
var body: some View {
let _ = Self._printChanges()
ScrollView {
LazyVStack(alignment: .leading, spacing: 2) {
ForEach(metadatas.chunked(into: columnCountStages[columnCountStagesIndex]), id: \.self) { rowMetadatas in
NCMediaRow(metadatas: rowMetadatas, isInSelectMode: $isInSelectMode, queuer: queuer) { tappedThumbnail, isSelected in
onCellSelected(tappedThumbnail, isSelected)
} onCellContextMenuItemSelected: { thumbnail, selection in
onCellContextMenuItemSelected(thumbnail, selection)
}
.equatable()
}
}
.padding(.top, 70)
.padding(.bottom, 40)
.scrollTargetLayout()
}
.scrollTargetBehavior(.viewAligned)
.refreshable {
await onRefresh()
}
.scrollPosition(id: $dataID, anchor: .bottom)
}
}
在父视图的视图模型中的某个位置,我调用:
self.metadatas.insert(contentsOf: updateMetadatas.metadatasUpdate, at: 0)
...将新项添加到此数组。然后,这将更新上述视图中的元数据。@Binding
问题在于,整个滚动视图的内容偏移量会发生变化以添加这些视图,而滚动视图又会向上推,而不是保持在与以前相同的位置。
由于(我假设)当您向下滚动时,唯一延迟加载视图,因此在顶部添加的任何视图都会在添加时呈现。这只是我的一个假设,问题可能出在别的地方。LazyVStack
我试图解决这个问题:
- 使用 iOS17 + .
scrollTargetLayout
scrollPosition
文档内容如下:
这有点模糊和令人困惑,但我认为当 .可悲的是,它似乎什么也没做。ScrollView
- 捕获滚动视图并在数组更改时再次设置它,但正如我之前提到的,添加新项目时 contentOffset 会增长,因此这并不能解决任何问题。
contentOffset
使用 a 是不可能的,因为它是一个非常有限的视图,并且会导致此自定义视图出现许多功能问题。List
有什么办法可以做到这一点吗?
答: 暂无答案
评论