#6 GeometryReader

GeometryReady 很费性能, 所以能不用就不用

功能

GeometryReader 不是布局容器,而是一个只读测量盒 :它把父视图分配给自己的实际尺寸与坐标 通过 GeometryProxy 实时向下注入,让子视图能够:

  • 按百分比计算帧大小
  • 实现屏幕驱动动画(3D 旋转、视差、滑动缩放等)
  • 获取全局坐标,用于拖拽、碰撞检测、滚动联动

API

swift 复制代码
GeometryReader { proxy in
    // 子视图
}

proxy 提供:

  • sizeCGSize ------ Reader 得到的确定尺寸

  • frame(in:) ------ 在不同坐标系里的 frame:

    • .local:自身坐标系
    • .global:屏幕原点
    • .named(id):自定义坐标空间(配合 .coordinateSpace(name:) 使用)
  • safeAreaInsets ------ 当前 Safe Area 插值

示例

swift 复制代码
struct GeometryReaderBootcamp: View {
    var body: some View {
        // GeometryReady 很费性能, 所以能不用就不用
        //        GeometryReader { geometry in
        //            HStack(spacing: 0) {
        //                Rectangle()
        //                    .fill(.red)
        //                    .frame(width: geometry.size.width * 0.66)
        //                Rectangle().fill(.blue)
        //            }
        //            .ignoresSafeArea()
        //        }
        
        ScrollView(.horizontal, showsIndicators: false) {
            HStack {
                ForEach(0..<20) { index in
                    GeometryReader { geometry in
                        RoundedRectangle(cornerRadius: 16)
                            .rotation3DEffect(
                                Angle(degrees: getPercentage(geometry: geometry) * 40),
                                axis: (x: 0, y: 1.0, z: 0.0))
                    }
                    .frame(width: 320, height: 240)
                    .padding()
                }
            }
        }
    }
        
    private func getPercentage(geometry: GeometryProxy) -> Double {
        let maxDistance = UIScreen.main.bounds.width / 2
        let currentX = geometry.frame(in: .global).midX
        
        return Double(1 - (currentX / maxDistance))
    }
}

性能与最佳实践

  1. 避免深层嵌套:布局阶段每帧都会重新调用闭包。
  2. 仅需尺寸时,优先使用 .frame(maxWidth: .infinity, maxHeight: .infinity) + 背景图层,代替嵌套 Reader。
  3. 需要全局坐标再 frame(in: .global),不要一上来就放在最外层。
  4. ScrollViewLazyVStack 联用时,把 Reader 放在叶子节点,减少重算范围。
  5. 若只关心 Safe Area 插值,可用 .padding(.safeArea) 替代 Reader。

小结

GeometryReader 是 SwiftUI 的"尺子"------不绘制、只测量

合理用它可实现百分比布局、视差动画、滑动联动等高级效果;

但牢记:能靠固有布局解决的,就不要让尺子上场。

相关推荐
开心就好20255 小时前
UniApp开发应用多平台上架全流程:H5小程序iOS和Android
后端·ios
开心就好20258 小时前
免 Xcode 的 iOS 开发新选择?聊聊一款更轻量的 iOS 开发 IDE kxapp 快蝎
后端·ios
恋猫de小郭11 小时前
Apple 的 ANE 被挖掘,AI 硬件公开,宣传的 38 TOPS 居然是"数字游戏"?
前端·人工智能·ios
东坡肘子15 小时前
OpenClaw 不错,但我好像没有那么需要 -- 肘子的 Swift 周报 #125
人工智能·swiftui·swift
忆江南1 天前
iOS 深度解析
flutter·ios
没有故事的Zhang同学1 天前
05-主题|事件响应者链@iOS-应用场景与进阶实践
ios
FeliksLv2 天前
尝试给Lookin 支持 MCP
ios
没有故事的Zhang同学2 天前
01-研究系统框架@Web@iOS | JavaScriptCore 框架:从使用到原理解析
ios
CocoaKier3 天前
苹果谷歌商店:如何监控并维护用户评分评论
ios·google·apple
iOS日常3 天前
iOS设备崩溃日志获取与查看
ios·xcode