SwiftUI 为我们提供了许多宝贵的方法来控制视图的对齐方式

最简单的对齐选项是frame修饰器的alignment参数。请记住,文本视图始终使用显示其文本所需的确切宽度和高度,但当我们在其周围放置一个可以具有任何大小的框架时。由于父级在子级的最终大小中没有发言权,因此这样的代码将创建一个 300x300 帧,其中以较小的文本视图为中心

struct sj_frame: View {
    var body: some View {
        Text("Live long and prosper")
            .border(Color.orange)
        .frame(width: 300, height: 300)
            .border(Color.black)
    }
}





swiftui AsyncImage 圆形 swiftui padding_基线


image.png


如果您不希望文本居中,请使用frame()的alignment参数。例如,此代码在从左到右的环境中运行时将视图放置在左上角

.frame(width: 300, height: 300, alignment: .topLeading)


swiftui AsyncImage 圆形 swiftui padding_技术交流_02


image.png


我们尚未在此处指定路线,因此默认情况下它们将居中。看起来不太好,所以您可能会考虑将它们全部对齐到一条边缘以获得更整齐的线条,如下所示

struct sj_frame_alignment: View {
    var body: some View {
       HStack {
      //  HStack(alignment: .bottom) {
            Text("Live")
                .font(.caption)
            Text("long")
            Text("and")
                .font(.title)
            Text("prosper")
                .font(.largeTitle)
        }
    }
}



swiftui AsyncImage 圆形 swiftui padding_技术交流_03


image.png


struct sj_frame_alignment: View {
    var body: some View {
      // HStack {
       HStack(alignment: .bottom) {
            Text("Live")
                .font(.caption)
            Text("long")
            Text("and")
                .font(.title)
            Text("prosper")
                .font(.largeTitle)
        }
    }
}



swiftui AsyncImage 圆形 swiftui padding_Text_04


image.png


但是,这看起来也很糟糕:因为每个文本视图的大小都不同,所以它们的基线也不同–这就是“ abcde”之类的字母在一行上的名称,不包括该行下方的字母作为“ gjpy”。结果,小文本的底部比大文本的底部低。

幸运的是,SwiftUI具有两个特殊的对齐方式,它们使第一个孩子或最后一个孩子的基线上的文本对齐。这将导致堆栈中的所有视图在一个统一的基准上对齐,无论其字体如何:

HStack(alignment: .lastTextBaseline) {



swiftui AsyncImage 圆形 swiftui padding_Text_05


image.png


继续,为了获得更细粒度的控制,我们可以自定义“对齐”对每个单独视图的含义。为了真正了解其工作原理,我们将从以下代码开始:

struct ContentView: View {
    var body: some View {
        VStack(alignment: .leading) {
            Text("Hello, world!")
            Text("This is a longer line of text")
        }
        .background(Color.red)
        .frame(width: 400, height: 400)
        .background(Color.blue)
    }
}



swiftui AsyncImage 圆形 swiftui padding_Text_06


image.png


运行该命令后,您会看到VStack紧紧围绕着两个带有红色背景的文本视图。两种文本视图的长度不同,但是由于我们使用了.lead对齐,因此它们在左右环境中都将对齐到其左边缘。除此之外,还有一个更大的框架,背景为蓝色。因为框架比VStack大,所以VStack位于中间。

现在,当VStack对齐所有这些文本视图时,它要求它们提供leading edge。默认情况下这很明显:根据系统语言,它使用视图的左边缘或右边缘。但是,如果我们要更改它,怎么办–如果我们要使一个视图具有自定义对齐方式,该怎么办?

为此,SwiftUI为我们提供了alignmentGuide()修饰符。这有两个参数:我们要更改的指南,以及一个返回新对齐方式的闭包。给闭包提供了一个ViewDimensions对象,该对象包含其视图的宽度和高度,以及读取其各种边缘的功能。

默认情况下,视图的.leader对齐指南是其leading
的对齐指南–我知道这很明显,但实际上等效于此:

VStack(alignment: .leading) {
    Text("Hello, world!")
        .alignmentGuide(.leading) { d in d[.leading] }
    Text("This is a longer line of text")
}



swiftui AsyncImage 圆形 swiftui padding_技术交流_07


image.png


我们可以重写该对齐指南,以将视图的trailing用作其前导对齐指南,如下所示:

VStack(alignment: .leading) {
    Text("Hello, world!")
        .alignmentGuide(.leading) { d in d[.trailing] }
    Text("This is a longer line of text")
}



swiftui AsyncImage 圆形 swiftui padding_技术交流_08


image.png


现在,您将看到为什么我要添加颜色:第一个文本视图将移至左侧,以便其右侧边缘位于下面视图的左侧边缘的正上方,VStack将展开以包含它,并且整个过程仍然在蓝框内居中。

此结果与使用offset()修饰符不同:如果偏移文本,则即使原始视图在不同位置呈现,其原始尺寸也不会实际改变。如果我们偏移了第一个文本视图而不是更改其对齐方式,则VStack不会扩展为包含它。

尽管AlignmentGuide是通过视图的尺寸传递的,但如果不需要,则不需要使用它们。您可以发送回硬编码的数字,或进行其他计算。例如,这通过将其位置乘以-10来为10个文本视图创建分层效果

var body: some View {
    VStack(alignment: .leading) {
        ForEach(0..<10) { position in
            Text("Number \(position)")
                .alignmentGuide(.leading) { _ in CGFloat(position) * -10 }
        }
    }
    .background(Color.red)
    .frame(width: 400, height: 400)
    .background(Color.blue)
}



swiftui AsyncImage 圆形 swiftui padding_技术交流_09


image.png