美文网首页Hacking with iOS: SwiftUI Edition
SwiftUI 布局: Alignment & Alignmen

SwiftUI 布局: Alignment & Alignmen

作者: 韦弦Zhy | 来源:发表于2020-12-04 16:49 被阅读0次

    \color{red}{\Large \mathbf{Hacking \quad with \quad iOS: SwiftUI \quad Edition}}

    {\Large \mathbf{Alignment \ and \ Alignment \ Guides}}

    SwiftUI 为我们提供了许多有价值的方法来控制视图的对齐方式,我将逐一介绍这些方法,以便您可以看到它们的实际操作。

    • 最简单的对齐选项是使用frame()修饰符的alignment参数。

    请记住,文本视图总是使用显示其文本所需的精确宽度和高度,但是当我们在其周围放置边框时,它可以是任何大小。由于父对象对子对象的最终大小没有发言权,因此这样的代码将创建一个300x300的框架,并在其内部以较小的文本视图为中心:

    Text("Live long and prosper")
        .frame(width: 300, height: 300)
    

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

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

    然后可以使用offset(x:y:)在 frame 内移动文本。

    • 下一个选项是使用堆栈的对齐参数。

    例如,这里有四个大小不同的文本视图排列在HStack中:

    HStack {
        Text("Live")
            .font(.caption)
        Text("long")
        Text("and")
            .font(.title)
        Text("prosper")
            .font(.largeTitle)
    }
    

    我们没有指定对齐方式,因此默认情况下它们将居中。这看起来不太好,所以您可能会考虑将它们全部对齐到一个边,以获得更整洁的线条,如下所示:

    HStack(alignment: .bottom) {
    

    然而,这看起来也很糟糕:因为每个文本视图的大小不同,它们也有不同的基线——这就是“abcde”之类的字母在一行上的名称,这不包括行下方的字母,如“gjpy”。因此,小文本的底部低于较大文本的底部。

    幸运的是,SwiftUI有两个特殊的对齐方式,可以在第一个子级或最后一个子级的基线上对齐文本。这将导致堆栈中的所有视图在一个统一基线上对齐,而不管它们的字体是什么:

    HStack(alignment: .lastTextBaseline) {
    

    接下来,为了实现更细粒度的控制,我们可以为每个单独的视图定制“对齐”的含义。为了更好地了解这是如何工作的,我们将从以下代码开始:

    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)
        }
    }
    

    运行时,您将看到VStack紧紧围绕着两个文本视图,背景为红色。两个文本视图的长度不同,但由于我们使用了.leading对齐方式,因此在从左到右的环境中,它们都将与它们的左边缘对齐。除此之外还有一个蓝色背景的大框架。因为frame大于VStack,所以以VStack中间为中心。

    现在,当VStack开始对齐这些文本视图时,它要求它们提供它们的 leading。默认情况下,这很明显:它使用视图的左边缘或右边缘,具体取决于系统语言。但是如果我们想改变这一点呢?如果我们想让一个视图具有自定义对齐方式呢?

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

    默认情况下,视图的.leading对齐向导是其.alignmentGuide(.leading)——我知道这听起来很明显,但实际上它相当于:

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

    我们可以重写该对齐向导,以使用视图的 trailing 作为其leading gaide 对齐向导,如下所示:

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

    现在您将看到我为什么要添加颜色:第一个文本视图将向左移动,以便它的右边缘位于下面视图的左边缘的正上方,VStack将展开以包含它,整个内容仍将位于蓝色框架的中心。

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

    虽然对齐导向闭包已传递给视图的尺寸,但如果不想使用,则不需要使用它们–可以发回硬编码的编号,或创建其他计算。例如,通过将10个文本视图的位置乘以-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)
    }
    

    要完全控制对齐指南,您需要创建自定义对齐指南。我认为这本书应该有一个小章节…

    Alignment and alignment guides

    相关文章

      网友评论

        本文标题:SwiftUI 布局: Alignment & Alignmen

        本文链接:https://www.haomeiwen.com/subject/sztliktx.html