Geometry Readers

背景阅读

  • SwiftUI内功之如何看待不完善的布局系统

我们可以使用GeometryReader进入布局过程。最重要的是,我们可以使用它来接收视图的建议布局大小。

GeometryReader配置有ViewBuilder(就像其他任何容器视图一样),但是与其他容器不同,几何读取器的视图构建器接收一个参数:GeometryProxy。代理具有用于视图的建议布局大小的属性,以及用于解析锚点的下标。在ViewBuilder中,我们可以使用此信息来布置子视图.

例如,如果我们要绘制一个矩形,其宽度是proposed(建议)大小的三分之一,则可以使用GeometryReader

import SwiftUI

struct ContentView: View {
    var body: some View {
        GeometryReader { proxy  in
            
            Rectangle()
                .fill(Color.red)
                .frame(width:proxy.size.width/3)
            
        }
    }
}





swiftui 改变image 图片 swiftui geometry_子视图


GeometryReader


使用GeometryReader时的一个重要警告是,它将GeometryReader报告为实际大小。由于这种尺寸调整行为,GeometryReader用作另一个视图的背景或叠加时通常特别有用:它们成为视图的确切大小。我们可以使用此大小在视图的边界中绘制某些内容,也可以测量视图的大小。


看个小demo

import SwiftUI

struct CircleDemo: View {
    var body: some View {
        VStack{
            Circle()
                .fill(Color.blue)
                .overlay(Circle().strokeBorder(Color.white).padding(3))
                .overlay(Text("Start").foregroundColor(.white))
                .frame(width:75,height:75)
        }
    }
}



swiftui 改变image 图片 swiftui geometry_子视图_02


image.png


不幸的是,我们不得不给按钮一个固定的大小。为了使其自动适应文本,我们可以采用一种简单的解决方法:我们可以将几何读取器放置在文本的背景内,然后使用它来绘制圆。通过在文本周围放置一些填充,圆会比文本稍宽.

import SwiftUI

struct CircleDemo: View {
    var body: some View {
        VStack{
            Circle()
                .fill(Color.blue)
                .overlay(Circle().strokeBorder(Color.white).padding(3))
                .overlay(Text("Start").foregroundColor(.white))
                .frame(width:75,height:75)
               
            
            Divider()
            
            Text("我爱北京天安门")
                .foregroundColor(.white)
            .padding(10)
            .background(
                GeometryReader { proxy in
                    Circle()
                        .fill(Color.blue)
                        .frame(width:proxy.size.width,height:proxy.size.width)
                    
                }
            
            )
        }
    }
}



swiftui 改变image 图片 swiftui geometry_Text_03


image.png


上述方法的一个问题是,整个视图的大小仍将是文本的大小加上填充的大小。圆的高度将被忽略。例如,如果我们使用.clipped()裁剪视图,它将仅显示一个蓝色矩形作为背景。同样,如果我们在垂直堆栈中放置多个类似的按钮,则圆圈将相互重叠

要解决此问题,我们可以在整个视图周围放置一个框架,使其宽度和高度与文本的宽度(加上填充)相同。不幸的是,在布局视图之前,我们不会知道文本的宽度。