SwiftUI布局之GeometryReader

36 阅读2分钟

🌐 一、GeometryReader 是什么?

GeometryReader 是一个视图容器,它会:

  • 占据父容器能给它的全部空间

  • 在其闭包中提供一个 GeometryProxy 对象;

  • 你可以通过这个 GeometryProxy 获取父布局信息,比如:

    • size(宽高)

    • safeAreaInsets

    • frame(in:)(在不同坐标空间中的位置)

它的基本形式如下:

GeometryReader { geometry in
    // 在这里使用 geometry 来计算布局
}

🧭 二、常用的 GeometryProxy 属性

属性类型说明
geometry.sizeCGSize当前 GeometryReader 的大小(宽高)
geometry.safeAreaInsetsEdgeInsets当前区域的安全区内边距
geometry.frame(in:)CGRect当前 GeometryReader 在指定坐标空间中的位置和大小

示例:

GeometryReader { geometry in
    Text("宽度:\(geometry.size.width),高度:\(geometry.size.height)")
        .frame(width: geometry.size.width / 2)
        .background(Color.blue)
}
.background(Color.gray)

上面这段代码会让 Text 视图的宽度占父视图的一半。


🧩 三、GeometryReader 的一个常见用途

1.相对定位布局

例如根据父视图宽高,让一个元素始终居中或相对某个位置布局:

GeometryReader { geo in
    Circle()
        .frame(width: 100, height: 100)
        .position(x: geo.size.width / 2, y: geo.size.height / 2)
}

2.响应滚动偏移(ScrollView + GeometryReader)

可以用来检测某个视图在滚动中的位置变化:

ScrollView {
    GeometryReader { geo in
        let offset = geo.frame(in: .global).minY
        Text("Offset: \(offset)")
            .padding()
            .background(Color.yellow)
    }
    .frame(height: 50)
}

这种技巧常用于制作滚动渐变效果、吸顶动画、折叠头图等。

3.根据容器尺寸自适应内容布局

比如动态调整字体大小、列数、间距:

GeometryReader { geo in
    let columns = Int(geo.size.width / 100)
    LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: columns)) {
        ForEach(0..<50) { index in
            Text("Item \(index)")
                .frame(height: 50)
                .background(Color.blue.opacity(0.3))
        }
    }
}

⚠️ 四、GeometryReader 的注意事项

  1. 它默认会“填满”父视图可用的空间

    因此很多人用时发现“布局乱了”或“撑满全屏”,这是正常行为。

    如果只想让它按内容大小布局,可以包一层固定大小的容器:

GeometryReader { geo in
    ...
}
.frame(height: 200) // 限定高度
  1. 不要滥用 GeometryReader 来布局所有东西

    SwiftUI 有自己的布局系统(HStack、VStack、ZStack、Layout 等),GeometryReader 主要用于需要知道“父容器的尺寸或位置”的时候。

  2. 避免在动画中频繁计算 GeometryReader 的值,因为它会触发布局重绘,影响性能。


🧠 五、总结一下它的角色

功能用途
读取父容器的几何信息size, position, safeAreaInsets
参与布局计算用于相对定位、自适应布局
配合滚动、动画响应位置变化,实现滚动特效

✅ 简短总结

GeometryReader = SwiftUI 的布局测量工具。

它不是布局方式,而是让你“知道布局尺寸和位置”的工具。

常用于实现动态、相对、响应式布局。