能否让SwiftUI的LazyVGrid滚动至指定项居中显示?
如何给LazyVGrid实现编程式滚动到指定项
问题场景
我有一个显示4列及大量图标的LazyVGrid,代码如下:
private var columns: [GridItem] = [ GridItem(.adaptive(minimum: .infinity, maximum: .infinity), spacing: 0), GridItem(.adaptive(minimum: .infinity, maximum: .infinity), spacing: 0), GridItem(.adaptive(minimum: .infinity, maximum: .infinity), spacing: 0), GridItem(.adaptive(minimum: .infinity, maximum: .infinity), spacing: 0) ] var body: some View { ScrollView{ //{ proxy in ZStack{ Color.blue LazyVGrid( columns: columns, alignment: .center, spacing: 10, pinnedViews: [] ) { ForEach(items, id:\.self.title) { item in Text(item.title) .listRowBackground(Color.clear) .id(item.title) .padding(.horizontal, 15) } } .listStyle(PlainListStyle()) } } }
现在我希望通过编程方式滚动该网格,使其显示特定的项。List可以轻松实现该功能,但LazyVGrid是否支持?
解决方案
LazyVGrid本身没有内置滚动控制API,但可以通过ScrollViewReader配合scrollTo方法实现需求,具体步骤如下:
- 替换ScrollView为ScrollViewReader:它会提供一个滚动代理,用于控制滚动行为
- 确保目标项有唯一ID:你已经给每个Text设置了
.id(item.title),需保证item.title全局唯一,否则滚动可能出错 - 调用scrollTo触发滚动:通过代理的
scrollTo(_:anchor:)方法,传入目标项的ID即可
修改后的完整代码示例:
// 存储要滚动到的目标项ID @State private var targetItemId: String? = nil // 固定4列建议用flexible,代替原有的adaptive(adaptive是自适应列数) private var columns: [GridItem] = [ GridItem(.flexible(), spacing: 0), GridItem(.flexible(), spacing: 0), GridItem(.flexible(), spacing: 0), GridItem(.flexible(), spacing: 0) ] var body: some View { ScrollViewReader { proxy in ZStack{ Color.blue LazyVGrid( columns: columns, alignment: .center, spacing: 10, pinnedViews: [] ) { ForEach(items, id:\.title) { item in Text(item.title) .listRowBackground(Color.clear) .id(item.title) .padding(.horizontal, 15) } } .listStyle(PlainListStyle()) // 监听目标ID变化,自动触发滚动 .onChange(of: targetItemId) { newValue in guard let id = newValue else { return } // anchor可设置滚动后目标项的位置:.top/.center/.bottom proxy.scrollTo(id, anchor: .top) } } // 示例:添加工具栏按钮触发滚动(实际可根据业务逻辑触发) .toolbar { Button("滚动到第10项") { targetItemId = items[9].title // 假设items是有序数组,取第10个元素的title } } } }
补充说明
- 若需要固定列数,
GridItem(.flexible())比.adaptive更合适,.adaptive是让系统根据屏幕宽度自动调整列数 scrollTo的anchor参数可自定义目标项滚动后的显示位置,按需选择- 若
items会动态更新,需保证id的唯一性和稳定性,避免滚动失效
内容的提问来源于stack exchange,提问作者Duck
相关产品推荐
相关产品推荐

