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

SwiftUI中HStack内LazyVGrid撑满屏宽适配全iPhone机型问题

SwiftUI 多LazyVGrid横向分页滑动适配问题修复方案

实现目标

  • 在横向容器内放置3个LazyVGrid组件
  • 每个LazyVGrid宽度与屏幕宽度完全一致
  • 默认状态下中间的LazyVGrid处于屏幕可视区域,其余两个分别位于屏幕左右外侧
  • 支持横向滑动切换三个Grid页面
  • 适配全尺寸iPhone设备

原有问题代码

@State private var numbers = [[1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7]]
private let columns = Array(repeating: GridItem(.flexible(minimum: 41, maximum: .infinity)), count: 7)

var body: some View {
    HStack(spacing: 10) {
        ForEach(numbers, id: \.self) { numberArray in
                LazyVGrid(columns: columns, alignment: .center, spacing: 0, pinnedViews: []) {
                    ForEach(numberArray, id: \.self) { number in
                        Text("\(number)")
                            .background(.blue.opacity(0.3))
                    }
                }
                .frame(maxWidth: .infinity)
                .background(.blue.opacity(0.1))
        }
    }
}

问题根源

  • 未给LazyVGrid明确指定与屏幕等宽的固定尺寸,仅用.frame(maxWidth: .infinity)会让HStack自动压缩/拉伸子视图宽度,导致不同尺寸屏幕下布局错乱
  • 普通HStack不具备横向滚动和分页能力,无法实现侧滑切换、默认定位中间页的效果
  • HStack设置了10的spacing,会导致分页对齐偏移、页面间出现多余间隙

修复后可直接运行的代码

import SwiftUI

struct GridPagingView: View {
    @State private var numbers = [[1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7]]
    private let columns = Array(repeating: GridItem(.flexible(), count: 7)
    // 初始定位到索引为1的中间页面
    @State private var scrollTarget: Int? = 1
    
    var body: some View {
        GeometryReader { proxy in
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 0) {
                    ForEach(Array(numbers.enumerated()), id: \.offset) { index, numberArray in
                        LazyVGrid(columns: columns, spacing: 0) {
                            ForEach(numberArray, id: \.self) { number in
                                Text("\(number)")
                                    .frame(maxWidth: .infinity)
                                    .padding(.vertical, 12)
                                    .background(.blue.opacity(0.3))
                            }
                        }
                        // 强制每个Grid宽度等于当前容器宽度,适配所有屏幕尺寸
                        .frame(width: proxy.size.width)
                        .background(.blue.opacity(0.1))
                        .id(index)
                    }
                }
                .scrollTargetLayout()
            }
            .scrollPosition(id: $scrollTarget)
            // 开启分页对齐效果
            .scrollTargetBehavior(.viewAligned)
            .ignoresSafeArea()
        }
    }
}

兼容说明

  • 若需要适配iOS 16以下系统,可通过UIViewRepresentable桥接UIScrollView的isPagingEnabled = true属性实现分页效果,替代scrollTargetBehavior
  • 用GeometryReader动态读取容器宽度而非硬编码UIScreen宽度,可自动适配横竖屏切换、iPad分屏等场景
  • 移除GridItem的minimum限制后,7列会自动均分屏幕宽度,不会出现小屏内容溢出、大屏列宽不均的问题

不同机型运行效果参考

  • iPhone 8运行效果:
    iPhone 8运行效果
  • iPhone 13 Pro Max运行效果:
    iPhone 13 Pro Max运行效果

内容的提问来源于stack exchange,提问作者Ammar Ahmad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 07:48:27