Text润饰符

  • AttributedString
  • multilineTextAlignment
  • format
  • tracking与knening
  • DateFormat
  • TextField
  • Label
  • TextPlaceholder
  • privacySensitive
  • 支撑Markdown
  • OpenURLAction
  • textSelection

概述

文章主要分享SwiftUI Modifier的学习进程,将运用事例的方法进行说明。内容浅显易懂,没有截图以直观的展现运行结果,不过测试代码是彻底的。假如想要运行结果,能够移步Github下载code -> github事例链接

1、运用AttributedString给Text增加款式

SwiftUI的Text视图能够烘托运用Foundation的AttributedString结构创立更杂乱的字符串,包含下划线删去线网页链接布景色彩

1.1、AttributedString通用特点创立Text

var message: AttributedString {
    var result = AttributedString("蜀道之难,难于上青天!")
    result.font = .largeTitle
    result.foregroundColor = .white
    result.backgroundColor = .red
    return result
}
Text(message)

1.2、多个AttributedString拼接

因为部分润饰是运用AttributedString自界说完结的,而不是Text,这意味着布景色彩是字符串本身的一部分,假如有需求,能够运用不同的布景色彩将多个字符串合并在一同。

var message1: AttributedString {
  var result = AttributedString("蜀道之难")
  result.font = .largeTitle
  result.foregroundColor = .white
  result.backgroundColor = .red
  return result
}
var message2: AttributedString {
  var result = AttributedString("难于上青天")
  result.font = .largeTitle
  result.foregroundColor = .white
  result.backgroundColor = .blue
  return result
}
Text(message1 + message2)

Text.background()无效问题:

当运用AttributedString润饰自界说字符串的时分,Text.background()润饰符是不起作用的

//接上面的比如
...
Text(message1 + message2)
    .background(.pink)

1.3、将单个字符上下偏移

var message4: AttributedString {
  let string = "蜀道之难,难于上青天!"
  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
}
Text(message4)

1.4、Link特点

var message5: AttributedString {
    var result = AttributedString("蜀道之难,难于上青天!")
    result.font = .largeTitle
    result.link = URL(string: "https://hanyu.baidu.com/shici/detail?from=kg1&highlight=&pid=6fbfb8ec1039475d9d4051021e19e661&srcid=51369")
    return result
}
Text(message5)

1.5、保留原数据

不会丢弃咱们供给有关字符串的所有原数据,例如(处于可访问性原因,咱们能够将字符串的一部分标记为需求拼写,以便在运用语音时正确读出密码等内容)

var message6: AttributedString {
    var password = AttributedString("abcdefg")
    password.accessibilitySpeechSpellsOutCharacters = true
    return "你的密码是:" + password
}
Text(message6)

1.6、结构化信息

处理结构化信息的方法,例如:假如咱们将Date实例格局化为特点字符串,它会保留每个组件代表的内容的知识 – 例如,它会记住“November”是字符串的月份部分

var message7: 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
}
Text(message7)

1.7、特别字符加粗效果(例如名人、地名)

处理人名时也是如此PersonNameComponents——这就是一个AttributedString比如,或人的姓氏是粗体的:

var message8: 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
}
Text(message8)

1.8、格局化测量单位

以下代码创立 200 公里的测量值,然后对其进行格局化,数值200显现的巨细远大于单位显现巨细:

var message9: AttributedString {
    let 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
}
Text(message9)

2、multilineTextAlignment() 调整文本对齐方法

当 SwiftUI 的Text视图跨多行换行时,它们默许与其左端对齐。假如你想更改它,运用multilineTextAlignment()润饰符指定代替项,例如.center、 或.trailing

2.1、多行文本换行居中

Text("蜀道之难,难于上青天!蚕丛及鱼凫,开国何茫然!尔来四万八千岁,不与秦塞通人烟。")
    .font(.largeTitle)
    .multilineTextAlignment(.center)
    .frame(width: 300)

2.2、运用picker挑选器动态修正3种对齐方法

let alignments: [TextAlignment] = [.leading, .center, .trailing]
@State private var alignment = TextAlignment.leading
var body: some View {
    List {
        Section() {
            Picker("Text alignment", selection: $alignment) {
                ForEach(alignments, id: \.self) { alignment in
                    Text(String(describing: alignment))
                }
            }
            Text("蜀道之难,难于上青天!蚕丛及鱼凫,开国何茫然!尔来四万八千岁,不与秦塞通人烟。")
                .font(.largeTitle)
                .multilineTextAlignment(alignment)
                .frame(width: 300)
        }
    }
}

3、运用format格局化文本

SwiftUI 的文本视图能够经过其format参数显现日期、数组、测量值等。

3.1、format: .list(type: .and)

假如将格局类型与字符串数组一同运用.list(),则能够取得格局规整的列表,例如“Howard、Josie 和 Kingsley”。例如,无论增加多少项目,这都将正确打印成分列表:

Text(ingredients, format: .list(type: .and))
Button("Add Ingredient") {
    let possibles = ["Egg", "Sausage", "Bacon","Spam"]
    if let newIngredieng = possibles.randomElement() {
        ingredients.append(newIngredieng)
    }
}

假如有一个数字类型的数组(例如整数),则能够经过指定成员款式来格局化该数组

Text(ingredients, format: .list(type: .and))
Button("Add Ingredient") {
    let possibles = ["Egg", "Sausage", "Bacon","Spam"]
    if let newIngredieng = possibles.randomElement() {
        ingredients.append(newIngredieng)
    }
}

3.2、.measurement()

假如您正在处理距离或重量等测量值,.measurement()格局类型将主动调整您的值以在用户区域设置中显现。例如,假如您在内部存储以厘米为单位的值,但用户设备上的区域设置为美国,iOS 将依据值的巨细主动显现以英尺或英寸为单位的值。

Text(rolls, format: .list(memberStyle: .number, type: .and))
Button("Roll Dice") {
    let result = Int.random(in: 1...6)
    rolls.append(result)
}

3.3、.currency(code: “CAD”)

格局化货币符号,保证显现的是两位小数,并依据需求增加货币符号

Text(72.3, format: .currency(code: "CAD"))

4、增加字母之间的距离

SwiftUI 为咱们供给了两个润饰符来操控文本企图内的字符距离,使咱们能够依据需求使字母距离更紧密或更远。两个润饰符是tracking()和kerning():都在字母之间增加距离,但tracking会将连体分开,而kerning不会,并且kerning会留下一些空白,而tracnking不会。

4.1、tracking()

将“Hello world”的tranking值设定为20,效果是字母键距离十分大

Text("Hello world")
    .tracking(20)

4.2 运用动态滑块Slider动态比较tracking与knening

比如运用了字体“AmericanTyperwriter”中的文本“ffi”,它有一个结合的字母子和,因为tracking会将结合分开,而kerning不会,所以当调整滑块的时分,第一个文本看起来像“f fi”,第二个文本看起来像“f f i”

@State private var amount = 50.0
var body: some View {
    List {
        Section {
            Text("ffi")
                .font(.custom("AmericanTyperwriter", size: 72))
                .kerning(amount)
            Text("ffi")
                .font(.custom("AmericanTyperwriter", size: 72))
                .tracking(amount)
            Slider(value: $amount, in: 0...100) {
                Text("Adjust the amount of spacing")
            }
        }
    }
}

5、格局化文本视图中的日期

SwiftUI 的文本企图附带两种特定的日期格局化函数,以使日期在屏幕上看起来更好:一种是用来处理耽误日期,另一种用来处理日期规模

5.1、addingTimeInterval

日期规模实际上十分简略,因为你只需求供给一个封闭的时刻规模,他将保证依据用户的区域设置正确的格局

Text(Date.now...Date.now.addingTimeInterval(600))

5.2、 运用style参数来确定日期的格局

// 只显现日期
Text(Date.now.addingTimeInterval(600), style: .date)
// 只显现时刻
Text(Date.now.addingTimeInterval(600), style: .time)
// 显现距离现在的相对时刻,主动更新(倒计时)
Text(Date.now.addingTimeInterval(600), style: .relative)
// 创立定时器款式,主动更新
Text(Date.now.addingTimeInterval(600), style: .timer)

6、运用 textCase() 将 TextField 设置为大写或小写

SwiftUI的TextField视图一般允许用户以他们想要的任何巨细写的形式修正内容,但假如你想操控它,你能够运用润饰符来强制运用大写或许小写textCase()

@State private var name = "Paul"
var body: some View {
    List() {
        Section {
            // 将用户输入的名字每个字母改成大写字母
            TextField("Shout your name at me", text: $name)
                .textFieldStyle(.roundedBorder)
                .textCase(.uppercase)
                .padding(.horizontal)
        }
    }
}

7、运用Label标签并排显现文本和图标

SwiftUI 有一个专属的视图类型,用于并排显现文本和图标,这对于菜单、列表十分有用

var body: some View {
    List {
        Section {
            //运用体系图库
            Label("Your Account", systemImage: "folder.circle")
            //运用自己导入的icon
            Label("Welcome to the app", image: "chincoteague")
            //能够运用修正器并行缩放文本和图标font()
            Label("Your Account", systemImage: "person.crop.circle")
                .font(.title)
        }
        Section {
            // labelStyle()能够运用.titleOnly、.iconOnly和.titleAndIcon来操控标签的显现方法
            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)
        }
        //彻底自界说
        Section {
            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)
            }
        }
    }
}

8、运用 redacted() 将内容标记为占位符

SwiftUI 允许咱们将文本标记为视图中的占位符,这就意味着它会被烘托,但会被灰色遮盖以标明它不是最终的内容。这是经过redacted(reason:)修正器供给的,以及unredacted()可依据需求用于覆盖密文的修正器

8.1、根底代码

Text("This is Placehoder text")
    font(.title)
    .redacted(reason: .placeholder)

8.2、能够将redacted润饰符提升到父控件以操控更多的Text

Section {
    Text("This is Placehoder text")
    Text("And so is thid")
}
.font(.title)
.redacted(reason: .placeholder)

8.3、依据环境变量确定现在Text的状况

苹果表明,这是一个附加的进程,这意味着假如你向父集和子集增加修正原因,那么他们就会合并。现在只要.placeholder,但或许咱们将来会看到像素化或相似的,你还能够查询从环境软儒的任何修正原因

struct FFTextPlaceholder: View {
    @Environment(\.redactionReasons) var redactionReasons
    let bio = "The rain in Span falls mainly on the Spaniards"
    var body: some View {
        List {
            Section {
                if redactionReasons == .placeholder {
                    Text("Loading...")
                } else {
                    Text(bio)
                        .redacted(reason: redactionReasons)
                }
            }
        }
    }
}

9、 运用privacySensitive()将内容标记为私有

SwiftUI 允许咱们将视图的某些部分标记为包含敏感信息,这实际上使咱们能够运用密文更轻松的躲藏或显现它。要在代码中运用此功能,请首先将privacySensitive()润饰符增加到想要躲藏的任何视图,然后将.redacted(reason: .privacy)润饰符应用到视图层次中更高的位置

9.1、privacySensitive

假如视图在非私有上下文中显现,则会躲藏用户的信誉卡号

Text("Card number")
    .font(.headline)
Text("1234 5678 9012 3456")
    .privacySensitive()

9.2、经过@Environment读取

默许情况下,因而敏感上下文被灰色框屏蔽,但你也能够经过从环境中读取密文来供给自界说布局

@Environment(\.redactionReasons) var redactionReasons
var body: some View {
    List {
        Section {
            Text("Card number")
                .font(.headline)
            if redactionReasons.contains(.privacy) {
                Text("[Hidden]")
            } else {
                Text("1234 5678 9012 3456")
            }
        }
    }
}

10、在Text中呈现 Markdown 内容

SwiftUI 内置了对Markdown烘托的支撑,包含粗体、斜体、链接等。它实际上内置SwiftUI的Text视图中

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

10.1、tint

该链接是能够点击的,默许情况下,Markdown链接将运用应用程序的强调色,但你能够运用tint()主题润饰符来更改它

Text("Visit Apple: [Click here](https://Apple.com)")
  .tint(.indigo)

10.2、LocallizedStringKey

发生这种主动Markdown转化是因为SwiftUI将这些字符串解释为LocallizedStringKey能够由咱们的应用程序本地化的字符串实例。这意味着假如你想从特点或许变量创立Markdown文本,你应该将其显现标记为LocallizedStringKey来获取Markdown的烘托

let markdownText: LocalizedStringKey = "* This is **bold** text,this is *italic* text, and this is ***bold, italic*** text."
Text(markdownText)

10.3、关于删去LocallizedStringKey和Text(verbatim:)

假如你期望原始的文本坚持不变,只需求删去类型LocallizedStringKey。或许,你也能够运用初始化程序彻底禁止Markdown和本地化Text(verbatim:)

let markdownText1 = "* This is **bold** text,this is *italic* text, and this is ***bold, italic*** text."
Text(markdownText1)
let markdownText2 = "* This is **bold** text,this is *italic* text, and this is ***bold, italic*** text."
Text(verbatim: markdownText2)

11、自界说Link处理方法

当你的用户点击了SwiftUIText或Link视图中显现的URL时,默许情况下它将在Safari中翻开。但是,你能够经过openURL环境密钥来自界说此行为-你可能期望自己处理链接,或许可能在自界说操作完结后将其传递回体系再翻开

var body: some View {
    List {
        Section {
            //此代码调整Link和Text视图,以便将所有URL发送到handleURL()要执行操作的方法
            Link("Visit Apple", destination: URL(string: "https://apple.com")!)
            Text("[Visit Apple](https://apple.com)")
        }
        .environment(\.openURL, OpenURLAction(handler: handleURL))
        //如上所示,handleURL()回来OpenURLAction.Result的值.handle,这意味着该方法接受了链接并对其进行了操作。当然还有其他枚举值能够操作:
        // .discarded:表明无法处理该链接
        // .systemAction假如你想触发默许行为(除了你自己的逻辑之外)
        // .systemAction(someOtherURL)假如你想运用默许行为翻开不同的URL(可能是开始护发的URL的修正版别)
        Section {
            //默许情况下链接将运用应用程序的强调色,但是能够运用主题润饰符修正tint()
            Text("[Visit Apple](https://apple.com)")
                .tint(.indigo)
        }
    }
}
func handleURL(_ url: URL) -> OpenURLAction.Result {
    print("Handle \(url) somehow")
    return .handled
}

12、Text的长按挑选

默许情况下,Swift的Text视图表明静态、不可挑选的文本,但是你能够运用.textSslection()带有值的润饰符来更改它为.enabled

12.1、textSelection长按敞开

挑选文本后,用户会主动取得对惯例文本操作的访问权限,例如仿制和共享。但是,现在至少整个文本区域都被仿制了–你没有文本挑选放大镜,所以你不能截选你想要的一小部分。

Text("You can't touch this")
Text("Break it down!")
    .textSelection(.enabled)

12.2、批量操作

对任何类型的视图组进行设置都会主动使该组内的所有文本都可挑选。例如,咱们能够经过将润饰符增加到外层的Section组件上来使两个Text文本都能够挑选copy

Section {
    Text("You can't touch this")
    Text("Break it down!")
}
.textSelection(.enabled)

注意:假如对list的section进行润饰,这个时分需求按住文本内容,点击空白处不会触发挑选