#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 的"尺子"------不绘制、只测量

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

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

相关推荐
1024小神12 小时前
xcode多环境 Dev 、Debug 和 Release变量配置以及怎么切换不同环境
开发语言·macos·ios·swiftui·xcode·swift
2501_9159184112 小时前
iOS 应用如何防止破解?从逆向链路还原攻击者视角,构建完整的反破解工程实践体系
android·macos·ios·小程序·uni-app·cocoa·iphone
他们都不看好你,偏偏你最不争气13 小时前
【iOS】MVVM
macos·ios·objective-c·cocoa
2501_9160074713 小时前
iOS 应用上架流程的工程化拆解 从签名体系到提交审核的全过程管控
android·ios·小程序·https·uni-app·iphone·webview
良逍Ai出海13 小时前
Vibecoding 开发前,要怎么去写一份面向Ai的需求文档
人工智能·ios·web app
一殊酒13 小时前
【前端开发】Uniapp:Android/IOS云打包
android·ios·uni-app
2501_9159184113 小时前
构建可靠的 iOS 日志导出体系,从真机日志到系统行为的多工具协同实践
android·ios·小程序·https·uni-app·iphone·webview
2501_9159090613 小时前
没有 Mac 怎么上架 iOS 应用 跨平台团队的可行交付方案分析
android·macos·ios·小程序·uni-app·iphone·webview
1024小神1 天前
Swift中跨view视图组件实现全局状态共享的方式汇总
ios·swiftui·swift