Text
是收缩型视图。Text
无论被如何截断,文本视图都会位于主视图的中心。除非被告知将视图放置在其他位置,否则它将相对于屏幕中心放置// 基本调用方法:Text 后面跟的参数必须是 String 类型
Text("Stay Hungry. Stay Foolish.")
// 字符串插值:如果要展示的信息不是 String 类型,需要用 \\() 进行插值
Text("\\(price)")
<aside> 💡 关于 iOS 设备默认的可用字体可以看这: http://iosfonts.com/ 。如果没有合适的字体,你还可以使用自己下载的合法的第三方字体。
</aside>
首先下载字体文件,并拖入项目文件夹里。
将字体文件拖到 Xcode 的项目导航器中。可以一次拖动包含 TrueType (.ttf) 或 OpenType (.otf) 文件的整个文件夹。接受默认设置;您确实想要复制项目、创建组并添加到当前目标。
您可以通过在项目导航器中选择字体文件,然后使用 Command-Option-1 打开 Xcode 的文件检查器窗格来检查字体文件是否已正确添加到当前目标。在项目导航器中突出显示每个字体文件,并确保其目标成员资格显示您应用程序的目标。
制作修改器 ViewModifier (其中字体名不需要加后缀)
struct CustomFontModifier : ViewModifier {
var size : CGFloat = 28
func body(content: Content) -> some View {
content
.font(.custom("Oswald-Regular", size: size))
}
}
修改 Info.plist
属性列表,新增 【Fonts provided by application】 字段
点击最左边导航中的项目根图标,找到Targets,点击项目名,在右边找到 info 子菜单。在Custom iOS Target Properties中,新增 Fonts provided by application 。做完后,左侧的项目导航目录里会多一项 info 文件。在 Fonts provided by application 里新增 item,后面填上字体的名称即可,有几个字体就新增几项。
在字段里逐个填入 item,即字体文件名,如:Oswald-Bold.ttf
//可以用 + 号连接多个文本(默认基线会对齐)
Text("Here is another ")
+ Text("example").foregroundColor(.red).underline()
+ Text("Notice").foregroundColor(.purple).bold()
+ Text("as a whole.").bold().italic()
//可以用 + 号连接多个文本(设置基线偏移,解决基线不对齐问题,负数代表往下)
Text("100").bold()
+ Text(" SWIFTUI ")
.baselineOffset(-12)
+ Text ("VIEWS").bold()
// 1. 将文本显示为占位符
// SwiftUI 允许将文本标记为视图中的占位符,这意味着它会被渲染,但会被灰色遮盖以表明它不是最终内容。
// 这是通过 redacted(reason:) 修饰符以及可用于根据需要覆盖密文的 unredacted() 修饰符提供的。
Text("This is placeholder text").redacted(reason: .placeholder)
// 还可以加到父元素上
VStack(alignment: .leading) {
Text("This is placeholder text This is placeholder telder tex")
Text("And so is this")
}.redacted(reason: .placeholder)
// 2. 还可以查询从环境传入的任何编辑原因
struct ContentView: View {
@Environment(\\.redactionReasons) var redactionReasons
let bio = "The rain in Spain falls mainly on the Spaniards"
var body: some View {
if redactionReasons == .placeholder {
Text("Loading…")
} else {
Text(bio)
.redacted(reason: redactionReasons)
}
}
}
// 3. 还允许将视图的某些部分标记为包含敏感信息,这使我们可以使用密文更轻松地隐藏或显示它
// 要使用此功能请将 privacySensitive() 修饰符添加到应隐藏的任何视图
// 然后在更高的视图层次结构中应用 .redacted(reason: .privacy) 修饰符
VStack {
Text("Card number")
.font(.headline)
if redactionReasons.contains(.privacy) {
Text("[HIDDEN]").privacySensitive()
} else {
Text("1234 5678 9012 3456").privacySensitive()
}
}
.redacted(reason: .privacy)
// 4.默认情况下,隐私敏感上下文被灰色框屏蔽,但您也可以通过从环境中读取密文原因来提供自定义布局:
struct ContentView: View {
@Environment(\\.redactionReasons) var redactionReasons
var body: some View {
VStack {
Text("Card number")
.font(.headline)
if redactionReasons.contains(.privacy) {
Text("[HIDDEN]")
} else {
Text("1234 5678 9012 3456")
}
}
}
}
Text
视图提供了两种使用 Markdown 设置文本样式的方法:直接在 Text
视图中和使用 AttributedString
。
直接在 Text
视图中使用 Markdown 对于静态文本来说很方便,但对于动态字符串或当您想要将样式应用于字符串的不同部分时,您需要使用 AttributedString
以编程方式。
// SwiftUI 内置了对 Markdown 渲染的支持,包括粗体、斜体、链接等
// 它实际上内置于 SwiftUI 的 Text 视图中,因此您可以编写如下代码:
VStack {
Text("This is regular text.")
Text("* This is **bold** text, this is *italic* text, and this is ***bold, italic*** text.")
Text("~~A strikethrough example~~")
Text("`Monospaced works too`")
Text("Visit Apple: [click here](<https://apple.com>)")
// 该链接是可自动点击的。默认情况下,Markdown 链接将使用应用程序的强调色,但可以使用 tint() 修饰符更改它:
Text("Visit Apple: [click here](<https://apple.com>)")
.tint(.indigo)
// 注意:不支持图像
}
// 支持自动 Markdown 转换是因为 SwiftUI 将这些字符串解释为 LocalizedStringKey 实例(即可以由应用程序本地化的字符串)
// 这意味着如果您想从属性或变量创建 Markdown 文本,您应该将其显式标记为 LocalizedStringKey 以获得 Markdown 渲染:
struct ContentView: View {
let markdownText: LocalizedStringKey = "* This is **bold** text, this is *italic* text, and this is ***bold, italic*** text."
var body: some View {
Text(markdownText)
}
}
// 如果希望原始文本保持不变(即将原始的、未格式化的 Markdown 符号保留在原处),只需删除 LocalizedStringKey 注释即可
// 或者,您可以使用 Text(verbatim:) 初始值设定项完全禁用 Markdown 和本地化。
Text
视图能够渲染 Foundation 的 AttributedString
结构,从而实现添加下划线、删除线、网页链接、背景颜色等效果。对于更高级或动态的样式, AttributedString
是首选工具。它允许您将不同的样式应用于字符串的不同部分。
AttributedString
的创建方式,是先声明一个 AttributedString
对象,然后再用点语法设置各个属性。
struct ContentView: View {
// 声明:先声明一个 AttributedString 对象,再设置其各种属性
var message: AttributedString {
var result = AttributedString("Hello, world!")
result.font = .largeTitle
return result
}
// 使用时:作为字符串传入到 Text
var body:some View {
Text(message)
}
}
遗憾的是, AttributedString
的 API 不大透明 ,所以这里展示一大堆示例来帮助入门。
// 字体大小
result.font = .largeTitle
// 前景色
result.foregroundColor = .white
// 背景色
result.backgroundColor = .red
// 下划线图案和颜色
result.underlineStyle = Text.LineStyle(pattern: .solid, color: .white)
// 使用 link 属性将可点击的网络链接附加到文本中
result.link = URL(string: "<https://www.hackingwithswift.com>")
// 还可以调整字符串各部分的基线偏移,强制将其放置在高于或低于默认值的位置:
struct ContentView: View {
var message: AttributedString {
let string = "The letters go up and down"
var result = AttributedString()
for (index, letter) in string.enumerated() {
var letterString = AttributedString(String(letter))
letterString.baselineOffset = sin(Double(index)) * 5
result += letterString
}
result.font = .largeTitle
return result
}
var body:some View {
Text(message)
}
}
使用 AttributedString 让 Text 展示多个样式:
该示例仅使用 Text
和常规 SwiftUI 修饰符来完成,但 AttributedString
的部分功能是自定义属于 String
而不是 Text
。这意味着背景颜色是 String
本身的一部分,因此如果需要,我们可以使用不同的背景颜色将多个 String
合并在一起:
struct ContentView: View {
// 声明红色背景的字符串
var message1: AttributedString {
var result = AttributedString("Hello")
result.font = .largeTitle
result.foregroundColor = .white
result.backgroundColor = .red
return result
}
// 声明蓝色背景的字符串
var message2: AttributedString {
var result = AttributedString("World!")
result.font = .largeTitle
result.foregroundColor = .white
result.backgroundColor = .blue
return result
}
// 使用时:
// 如果您尝试对 Text 使用 background() 修饰符,会发现它不起作用。
var body:some View {
Text(message1 + message2)
}
}
<aside>
💡 您可以将 SwiftUI 修饰符与 AttributedString
属性混合使用。重要的是,通过 AttributedString
应用的属性优先于 SwiftUI 修饰符。
</aside>
在此示例中, AttributedString
使用 Markdown 语法来制作一些斜体文本。当此 AttributedString
传递到 Text
视图时,这些样式将被保留。当将 font
和 foregroundColor
修饰符应用于 Text
视图时,这些样式将应用于整个文本,但它们不会覆盖粗体和由 AttributedString
指定的斜体样式。
这是因为 AttributedString
的样式优先于 SwiftUI 修饰符。
let quote = """
**"Be yourself;** everyone else is _already taken._"
- **Oscar Wilde**
"""
let attributedQuote = try! AttributedString(markdown: quote)
struct ContentView: View {
var body: some View {
Text(attributedQuote)
.font(.system(size: 16, weight: .medium, design: .serif))
.foregroundColor(.blue)
}
}
AttributedString
真正强大的功能是它不会丢弃我们提供的有关字符串的所有元数据,这解锁了大量额外的功能。例如,出于可访问性原因,我们可以将字符串的一部分标记为需要拼写,以便在使用 VoiceOver 时正确读出密码等内容:
struct ContentView: View {
var message: AttributedString {
var password = AttributedString("abCayer-muQai")
password.accessibilitySpeechSpellsOutCharacters = true
return "Your password is: " + password
}
var body:some View {
Text(message)
}
}
更令人印象深刻的是它处理结构化信息的方式。
例如,如果我们将 Date
实例格式化为属性字符串,它会保留每个组件代表的内容的知识,它会记住“November”是字符串的月份部分。这意味着我们可以根据语义设置字符串的样式:我们可以设置 “工作日部分具有主要颜色,而其他具有次要颜色”,如下所示:
struct ContentView: View {
var message: AttributedString {
var result = Date.now.formatted(.dateTime.weekday(.wide).day().month(.wide).attributed)
result.foregroundColor = .secondary
let weekday = AttributeContainer.dateField(.weekday)
let weekdayStyling = AttributeContainer.foregroundColor(.primary)
result.replaceAttributes(weekday, with: weekdayStyling)
return result
}
var body:some View {
Text(message)
}
}
// 请注意:该代码不知道工作日实际出现在文本中的位置(它与语言和区域设置无关),因此它可以为每个人正确设置样式。
使用 PersonNameComponents
处理人名也是如此。以下例子产生一个 AttributedString
实例,其中某人的姓氏是粗体的:
struct ContentView: View {
var message: AttributedString {
var components = PersonNameComponents()
components.givenName = "Taylor"
components.familyName = "Swift"
var result = components.formatted(.name(style: .long).attributed)
let familyNameStyling = AttributeContainer.font(.headline)
let familyName = AttributeContainer.personNameComponent(.familyName)
result.replaceAttributes(familyName, with: familyNameStyling)
return result
}
var body:some View {
Text(message)
}
}
您甚至可以将其用于测量。例如,以下代码创建 200 公里的测量值,然后对其进行格式化,以便显示的值远大于单位:
struct ContentView: View {
var message: AttributedString {
var amount = Measurement(value: 200, unit: UnitLength.kilometers)
var result = amount.formatted(.measurement(width: .wide).attributed)
let distanceStyling = AttributeContainer.font(.title)
let distance = AttributeContainer.measurement(.value)
result.replaceAttributes(distance, with: distanceStyling)
return result
}
var body:some View {
Text(message)
}
}
// 作为奖励,这将自动尊重用户对距离的区域设置偏好,这意味着许多用户将看到“124 英里”而不是“200 公里”。
<aside> 💡 警告:如果您使用 Xcode 的自动完成功能探索 API,您将看到各种看起来应该有效的选项,但实际上都是无效的。
</aside>
// 方式:使用 SF 符号
Label("Welcome to the app", systemImage: "folder.circle")
// 方式:使用自己的图片资源
Label("Welcome to the app", image: "star")
// 方式:Label 包含 title 和 icon 两个属性,可以快速放置 图片 和 文字,而不必使用布局视图
Label(
title:{
Text("Delete").fontWeight(.semibold)
}
icon:{
Image(systemName:"trash").font(.title)
}
)
// 方式:还可以为文本和图像提供完全自定义的视图
Label {
Text("Paul Hudson")
.foregroundStyle(.primary)
.font(.largeTitle)
.padding()
.background(.gray.opacity(0.2))
.clipShape(Capsule())
} icon: {
RoundedRectangle(cornerRadius: 10)
.fill(.blue)
.frame(width: 64, height: 64)
}
**控制标签显示方式:**通过 .labelStyle()
修饰符,可以控制标签的显示方式,其支持参数值有automatic
、 .titleOnly
、 .iconOnly
和 .titleAndIcon
VStack {
Label("Text Only", systemImage: "heart")
.font(.title)
.labelStyle(.titleOnly)
Label("Icon Only", systemImage: "star")
.font(.title)
.labelStyle(.iconOnly)
Label("Both", systemImage: "paperplane")
.font(.title)
.labelStyle(.titleAndIcon)
}
SwiftUI 的文本视图能够通过设置 format
参数,从而显示日期、数组、测量值等。不过,此功能仅在 iOS 15 中可用,因此对于 iOS 14 和 13 支持,请参阅下面的 formatter
参数。
// 显示为数字
Text("转换结果是: \\(finalValue.formatted(.number))")
// 保留小数点后两位
Text("转换结果是: \\(String(format: "%.2f", finalValue))")
将 .list()
格式类型与字符串数组一起使用,则可以获得格式整齐的列表展示,例如“Howard、Josie 和 Kingsley”。
// 例如,无论添加多少项目,这都将正确打印成员列表:
struct ContentView: View {
@State private var ingredients = [String]()
var body:some View {
VStack {
Text(ingredients, format: .list(type: .and))
Button("Add Ingredient") {
let possibles = ["Egg", "Sausage", "Bacon", "Spam"]
if let newIngredient = possibles.randomElement() {
ingredients.append(newIngredient)
}
}
}
}
}
// 显示: Spam, Egg, Sausage, and Bacon
如果是数字类型的数组(例如整数),则可以通过指定 memberStyle
来格式化该数组,如下所示:
struct ContentView: View {
@State private var rolls = [Int]()
var body:some View {
VStack {
Text(rolls, format: .list(memberStyle: .number, type: .and))
Button("Roll Dice") {
let result = Int.random(in: 1...6)
rolls.append(result)
}
}
}
}
// 显示: 4, 3, 2, and 6
当您正在处理距离或重量等测量值, .measurement()
格式类型将自动调整您的值以在用户区域设置中显示。例如,如果您在内部存储以厘米为单位的值,但用户设备上的区域设置为美国,iOS 将根据值的大小自动显示以英尺或英寸为单位的值。
struct ContentView: View {
let length = Measurement(value: 225, unit: UnitLength.centimeters)
var body:some View {
Text(length, format: .measurement(width: .wide))
}
}
还有一个格式化程序可以正确处理货币,确保显示两位小数,并根据需要添加货币符号:
Text(72.3, format: .currency(code: "CAD"))
//使用当地语言的货币符号(用户如果没有设置,则使用默认值 USD)
TextField(
"Amount", value: $checkAmount, format: .currency(code: Locale.current.currency?.identifier ?? "USD")
)
SwiftUI 的文本视图附带两种特定的日期格式化程序,以使日期在屏幕上看起来更好:一种用于处理单个日期,另一种用于处理日期范围。
**日期范围:**实际上更简单,因为您只需提供一个封闭的日期范围,它将确保其根据用户的区域设置进行适当的格式化: