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

如何在SwiftUI的LazyVGrid中适配iPhone与iPad的列数?

SwiftUI LazyVGrid 多设备适配与行数限制方案

一、实现多设备列数适配

要让iPhone每行显示2个条目、iPad每行显示4个,可通过动态生成GridItem数组实现,推荐两种实用方式:

方式1:直接区分设备类型

通过UIDevice的设备类型判断,快速生成对应列数的布局:

private var gridItemLayout: [GridItem] {
    // iPad显示4列,iPhone显示2列
    let columnCount = UIDevice.current.userInterfaceIdiom == .pad ? 4 : 2
    // 用flexible让列宽自动均分可用空间,同时设置列间距
    return Array(repeating: GridItem(.flexible(), spacing: 20), count: columnCount)
}

方式2:基于尺寸类适配(更灵活)

利用SwiftUI的horizontalSizeClass环境变量,不仅适配设备,还能支持iPad分屏场景(比如iPad分屏为紧凑宽度时自动切换为2列):

@Environment(\.horizontalSizeClass) private var horizontalSizeClass

private var gridItemLayout: [GridItem] {
    // 常规宽度(iPad全屏)显示4列,紧凑宽度(iPhone、iPad分屏)显示2列
    let columnCount = horizontalSizeClass == .regular ? 4 : 2
    return Array(repeating: GridItem(.flexible(), spacing: 20), count: columnCount)
}

二、限制LazyVGrid的行数

LazyVGrid没有直接的行数限制API,可通过截取数据源前N个元素实现,计算公式:显示元素总数 = 列数 × 最大行数。

比如限制显示2行,代码修改如下:

ScrollView {
    LazyVGrid(columns: gridItemLayout, spacing: 20) {
        // 自定义最大行数
        let maxRows = 2
        // 计算需显示的元素数量,截取数据源前N个
        let displayResults = Array(viewModel.results.prefix(gridItemLayout.count * maxRows))
        
        ForEach(displayResults, id: \.self) { item in
            let resultVM = ResultVM(model: item)
            NavigationLink(destination: DetailView()) {
                SearchResultRow(resultVM: resultVM)
            }
        }
    }
}

三、完整修改后的代码

//
//  ContentView.swift
//  DemoProject
//

import SwiftUI
import CoreData

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext
    @Environment(\.horizontalSizeClass) private var horizontalSizeClass
    
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)],
        animation: .default)
    private var items: FetchedResults<Item>
    
    @StateObject private var viewModel = HomeViewModel()
    
    // 动态生成GridItem布局
    private var gridItemLayout: [GridItem] {
        let columnCount = horizontalSizeClass == .regular ? 4 : 2
        return Array(repeating: GridItem(.flexible(), spacing: 20), count: columnCount)
    }

    var body: some View {
        NavigationView {
            ScrollView {
                LazyVGrid(columns: gridItemLayout, spacing: 20) {
                    // 限制显示2行
                    let maxRows = 2
                    let displayResults = Array(viewModel.results.prefix(gridItemLayout.count * maxRows))
                    
                    ForEach(displayResults, id: \.self) { item in
                        let resultVM = ResultVM(model: item)
                        NavigationLink(destination: DetailView()) {
                            SearchResultRow(resultVM: resultVM)
                        }
                    }
                }
                .padding() // 给Grid添加内边距,避免内容贴边
            }
            .navigationTitle("搜索结果")
        }
        .onAppear {
            viewModel.performSearch()
        }
    }
}

struct SearchResultRow: View {
    let resultVM: ResultVM
    
    var body: some View {
        RoundedRectangle(cornerRadius: 16)
            .fill(.yellow)
            .aspectRatio(1, contentMode: .fit) // 保持正方形比例
            .overlay(Text(resultVM.trackName).foregroundColor(.black))
            .padding()
            .background(Color.red)
    }
}

四、效果说明

  • iPhone设备/ iPad紧凑宽度模式:每行显示2个条目,最多显示2行共4个元素
  • iPad全屏模式:每行显示4个条目,最多显示2行共8个元素

内容的提问来源于stack exchange,提问作者New iOS Dev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 10:36:22