SwiftUI文本对齐

334

在众多属性中,我找不到任何与文本对齐相关的属性。我在演示中看到它会自动处理RTL,并且使用View的放置内容时,它会自动居中。

我是否缺少有关布局系统的某些概念?如果没有,如何设置Text的文本对齐属性?

15个回答

517
你可以通过修改器 .multilineTextAlignment(.center) 来实现这个功能。
Text("CENTER")
    .multilineTextAlignment(.center)

苹果文档


19
有没有什么东西可以使文本两端对齐? - theMouk
8
这些似乎只在文本足够长时才起作用。所以这个例子不起作用吗? - Christopher
@Christopher:如果文本内容不足以换行,并且您没有填充父视图,它将占用所需的空间来显示文本,因此在完全相同大小的空间中居中,这并没有什么作用。尝试为您的文本添加边框,看看我的意思是什么。 - vrwim
请参见StaticVoidMan的下面回答。 - stromyc

355

从SwiftUI beta 3开始,您可以使用frame修饰符将文本视图居中:

Text("Centered")
    .frame(maxWidth: .infinity, alignment: .center)

13
由于某种原因,“.multilineTextAlignment()”没有给我想要的结果,但这个方法可以。 - Chad Mx
3
这对大多数情况都不起作用。 - Arturo
这个原因是因为如果它是一个紧密的正方形,无论是对齐到前导、中央还是后尾,效果都是一样的,因为它只是被挤在那里。但是框架会扩展那个正方形,所以对齐方式更具意义。 - Mostafa ElShazly

233

我试图理解这个问题,因为其他答案提到了 Text.multilineTextAlignment(_:) / VStack(alignment:) / frame(width:alignment:),但每个解决方案都解决一个特定的问题。最终取决于UI要求和这些解决方案的组合。


VStack(alignment:)

这里的alignment是关于内部视图相互之间的对齐。
因此,指定.leading会将所有内部视图与彼此的前导边对齐。

VStack(alignment: .leading, spacing: 6) {
  Text("Lorem ipsum dolor")
        .background(Color.gray.opacity(0.2))
  Text("sit amet")
        .background(Color.gray.opacity(0.2))
}
.background(Color.gray.opacity(0.1))

图片


.frame

frame(width:alignment:)frame(maxWidth:alignment:)中,alignment是指给定宽度内的内容对齐方式。

VStack(alignment: .leading, spacing: 6) {
  Text("Lorem ipsum dolor")
      .background(Color.gray.opacity(0.2))
  Text("sit amet")
      .background(Color.gray.opacity(0.2))
}
.frame(width: 380, alignment: .trailing)
.background(Color.gray.opacity(0.1))

内部视图彼此之间是左对齐的,但视图本身相对于 VStack 是右对齐的。

image


.multilineTextAlignment

这指定了文本的对齐方式,并且在有多行时最为明显。否则,如果没有定义 frame(width:alignment),宽度会自动调整,并受默认的 alignment 影响。

VStack(alignment: .trailing, spacing: 6) {
  Text("0. automatic frame\n+ view at parent's specified alignment\n+ multilineTA not set by default at leading")
    .background(Color.gray.opacity(0.2))
  Text("1. automatic frame\n+ view at parent's specified alignment\n+ multilineTA set to center")
  .multilineTextAlignment(.center)
  .background(Color.gray.opacity(0.2))
  Text("2. automatic frame\n+ view at parent's specified alignment\n+ multilineTA set to trailing")
  .multilineTextAlignment(.trailing)
  .background(Color.gray.opacity(0.2))
}
.frame(width: 380, alignment: .trailing)
.background(Color.gray.opacity(0.1))

image


组合测试:

VStack(alignment: .trailing, spacing: 6) {
  Text("1. automatic frame, at parent's alignment")
  .background(Color.gray.opacity(0.2))
  Text("2. given full width & leading alignment\n+ multilineTA at default leading")
  .frame(maxWidth: .infinity, alignment: .leading)
  .background(Color.gray.opacity(0.2))
  Text("3. given full width & center alignment\n+ multilineTA at default leading")
  .frame(maxWidth: .infinity, alignment: .center)
  .background(Color.gray.opacity(0.2))
  Text("4. given full width & center alignment\n+ multilineTA set to center")
  .multilineTextAlignment(.center)
  .frame(maxWidth: .infinity, alignment: .center)
  .background(Color.gray.opacity(0.2))
  Text("5. given full width & center alignment\n+ multilineTA set to trailing")
  .multilineTextAlignment(.trailing)
  .frame(maxWidth: .infinity, alignment: .center)
  .background(Color.gray.opacity(0.2))
  Text("6. given full width but no alignment\n+ multilineTA at default leading\n+ leading is based on content, looks odd sometimes as seen here")
  .frame(maxWidth: .infinity)
  .background(Color.gray.opacity(0.2))
}
.frame(width: 380)
.background(Color.gray.opacity(0.1))

image


7
这是一个非常有说服力的答案,谢谢。我会考虑将其视为另一个被采纳的答案。 - inokey
2
@inokey 很高兴分享我的观察 :) 后来我发现了一篇更深入介绍视图对齐的有趣文章:SwiftUI 中的对齐指南 - staticVoidMan
太棒了, SwiftUI 自我最初发布以来真的有很大的进步。 - inokey
你知道为什么多行文本如果我加上 Spacer().frame(height: 50) 就会变成一行吗?如果我从spacer中删除高度,多行文本就会显示所有行。我该如何强制显示所有行? - fullmoon
1
我讨厌这不是被接受的答案。谢谢。 - Ale Ravasio

34

我曾经遇到过需要将文本对齐到同一行的问题。我发现以下方法管用:

Text("some text")
    .frame(alignment: .leading)
如果与框架宽度参数结合使用,您可以为标签等获得一些漂亮的文本块格式。

31

我猜想SwiftUI希望我们使用像stacks这样的包装器来完成这样的事情。

因此,与其编写像Text("Hello World").aligned(.leading)这样的内容,更加推荐以下方式:

VStack(alignment: .leading) {
    Text("Hello World")
}

1
那么我不能简单地放弃一个与堆栈无关的标签吗? - inokey
@inokey,我至少没有找到这个的修饰符。 - fredpi
我也没有。对我来说,好像我错过了SUI的某种基本概念。我甚至不能仅仅在两个元素之间放置“视图”,并给它一个颜色,就像它们没有普通的a-la-uiview对象一样。 - inokey
1
框架修饰符具有对齐参数。 - EmilioPelaez
1
似乎做这件事情有些愚蠢(尽管它确实有效)。你听谁说鼓励这么做的? - MobileMon

21

我们需要对齐文本而不是它所在的堆栈。因此,调用 multilineTextAlignment(.center) 并设置行限制,我可以看到文本居中对齐。我不知道为什么需要设置行限制,我原以为如果有大段文字就会自动扩展。

Text("blahblah")
        .font(.headline)
        .multilineTextAlignment(.center)
        .lineLimit(50)

19

我也遇到了同样的问题。 我用这个来修复它。

Text("Test")
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)

1
这会产生非常奇怪的结果,我不建议。 - Samuel Owino
这解决了我的问题。我尝试实现GridItem(s),里面有Circle()和Text()。但是文本的对齐方式使我的UI变得混乱。经过2个小时的尝试,这个答案拯救了我!JazakAllah Khair Kaseera。 - Mubin Mall

17
如果您想保持文本的恒定宽度,那么“ .multilineTextAlignment(.leading)”在只有一行文本时不会产生任何效果。
这是对我有效的解决方案:
struct LeftAligned: ViewModifier {
    func body(content: Content) -> some View {
        HStack {
            content
            Spacer()
        }
    }
}


extension View {
    func leftAligned() -> some View {
        return self.modifier(LeftAligned())
    }
}

使用方法:

Text("Hello").leftAligned().frame(width: 300)

14

您可以将垂直 StackView 的对齐方式设置为 leading。如下所示

 VStack(alignment: .leading) {
            Text("Turtle Rock")
                .font(.title)
            Text("Joshua Tree National Park")
                .font(.subheadline)
        }

输入图像描述


14
我想使用 Spacer() 视图来对齐文本块。这个例子展示了文本在结尾的一侧:
HStack{
    Spacer()
    Text("Wishlist")
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接