添加新项目时如何保持 ScrollView+LazyVStack 滚动位置

How to keep ScrollView+LazyVStack scroll position when adding new items

提问人:Milen Pivchev 提问时间:11/16/2023 最后编辑:Milen Pivchev 更新时间:11/16/2023 访问量:37

问:

我有以下观点:

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


我试图解决这个问题:

  1. 使用 iOS17 + .scrollTargetLayoutscrollPosition

文档内容如下:

enter image description here

这有点模糊和令人困惑,但我认为当 .可悲的是,它似乎什么也没做。ScrollView

  1. 捕获滚动视图并在数组更改时再次设置它,但正如我之前提到的,添加新项目时 contentOffset 会增长,因此这并不能解决任何问题。contentOffset

使用 a 是不可能的,因为它是一个非常有限的视图,并且会导致此自定义视图出现许多功能问题。List

有什么办法可以做到这一点吗?

iOS Swift SwiftUI

评论


答: 暂无答案