利用 AttributedString 或 NSAttributedString 實現多種樣式組合的文字

開發 iOS App 時,我們時常會看到多種樣式組合的文字,比方下圖 IG App 紅色框框的文字區塊,人名 anwei20 跟終於 … 的文字是不同的樣式。

利用 AttributedString 或 NSAttributedString 將可實現多種樣式組合的文字效果,以下彼得潘將以戴佩妮創作的好聽歌曲天花版的星星說明。

從 Xcode playground 實驗 AttributedString

透過 iOS 15 推出的 AttributedString,我們可以實現多種樣式組合的文字效果。以下為 Xcode playground 的程式範例。

import UIKit

var content = AttributedString()
var name = AttributedString("anwei20 ")
name.font = .boldSystemFont(ofSize: 30)
name.foregroundColor = UIColor.black
content += name

var message = AttributedString("戴佩妮創作的天花版的星星\n")
message.font = .systemFont(ofSize: 18)
message.foregroundColor = UIColor.gray
content += message

var lyrics = AttributedString("看你從没看過的風景 躲没躲過的大雨 創造一個天晴 避開你最討厭的擁擠 你最害怕的猜疑 好好喘口氣")
lyrics.font = .systemFont(ofSize: 14)
lyrics.foregroundColor = UIColor.systemPink
lyrics.backgroundColor = UIColor.cyan
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 5
lyrics.paragraphStyle = paragraphStyle
content += lyrics

let label = UILabel()
label.attributedText = NSAttributedString(content)
label.numberOfLines = 0
let size = label.sizeThatFits(CGSize(width: 300, height: 0))
label.frame.size = size
label.backgroundColor = .white
label

說明

message.foregroundColor = UIColor.gray

UIColor.gray 如果要省略成 .gray,可改成 message.uiKit.foregroundColor,讓程式知道我們指的是 UIKit 的顏色,不是 SwiftUI 的顏色。

label.attributedText = NSAttributedString(content)

由於 attributedText 的型別是 NSAttributedString,因此我們要從型別AttributedString 的 content 生成 NSAttributedString,才能存入 attributedText。

接下來讓我們搭配 storyboard 設計的 App 畫面,實驗 AttributedString & NSAttributedString 組合文字的效果。

storyboard 的畫面設計

iOS 15 以上: 使用 AttributedString

透過 AttributedString 的各種屬性設定文字樣式,比方字體,文字顏色,背景顏色,行距等。

class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!

override func viewDidLoad() {
super.viewDidLoad()

var content = AttributedString()

var name = AttributedString("anwei20 ")
name.font = .boldSystemFont(ofSize: 30)
name.foregroundColor = UIColor.black
content += name

var message = AttributedString("戴佩妮創作的天花版的星星\n")
message.font = .systemFont(ofSize: 18)
message.foregroundColor = UIColor.gray
content += message

var lyrics = AttributedString("看你從没看過的風景 躲没躲過的大雨 創造一個天晴 避開你最討厭的擁擠 你最害怕的猜疑 好好喘口氣")
lyrics.font = .systemFont(ofSize: 14)
lyrics.foregroundColor = UIColor.systemPink
lyrics.backgroundColor = UIColor.cyan
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 5
lyrics.paragraphStyle = paragraphStyle
content += lyrics

label.attributedText = NSAttributedString(content)

}
}

當 AttributedString 的文字有不同大小時,預設將對齊文字底部,因此上圖的 anwei20 & 戴佩妮創作的天花版的星星底部對齊。

不過我們也可以透過 baselineOffset 微調整對齊,比方以下例子將讓戴佩妮創作的天花版的星星向上移動,實現 anwei20 & 戴佩妮創作的天花版的星星置中對齊的效果。

var message = AttributedString("戴佩妮創作的天花版的星星\n")
message.font = .systemFont(ofSize: 18)
message.foregroundColor = UIColor.gray
message.baselineOffset = 4

舊版: 使用 NSAttributedString

class ViewController: UIViewController {

@IBOutlet weak var label: UILabel!

override func viewDidLoad() {
super.viewDidLoad()

let content = NSMutableAttributedString()

let name = NSMutableAttributedString(string: "anwei20 ", attributes: [
.font: UIFont.boldSystemFont(ofSize: 30),
.foregroundColor: UIColor.black
])
content.append(name)

let message = NSMutableAttributedString(string: "戴佩妮創作的天花版的星星\n", attributes: [
.font: UIFont.systemFont(ofSize: 18),
.foregroundColor: UIColor.gray
])
content.append(message)

let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 5
let lyrics = NSMutableAttributedString(string: "看你從没看過的風景 躲没躲過的大雨 創造一個天晴 避開你最討厭的擁擠 你最害怕的猜疑 好好喘口氣", attributes: [
.font: UIFont.systemFont(ofSize: 14),
.foregroundColor: UIColor.systemPink,
.backgroundColor: UIColor.cyan,
.paragraphStyle: paragraphStyle
])
content.append(lyrics)

label.attributedText = content
}
}

當 NSMutableAttributedString 的文字有不同大小時,預設將對齊文字底部,因此上圖的 anwei20 & 戴佩妮創作的天花版的星星底部對齊。

不過我們也可以透過 baselineOffset 微調整對齊,比方以下例子將讓戴佩妮創作的天花版的星星向上移動,實現 anwei20 & 戴佩妮創作的天花版的星星置中對齊的效果。

let message = NSMutableAttributedString(string: "戴佩妮創作的天花版的星星\n", attributes: [
.font: UIFont.systemFont(ofSize: 18),
.foregroundColor: UIColor.gray,
.baselineOffset: 4
])

作品集

--

--

彼得潘的 iOS App Neverland
彼得潘的 Swift iOS App 開發問題解答集

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com