You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 20:42:28