第 32 章
使用 TextEditor 支援多行文字輸入
SwiftUI 的第一個版本(隨 iOS 13 推出)沒有提供用於支援多行文字輸入的文本視圖(Text View)。 如要使用的話,就需要從 UIKit 框架中借用 UITextView
,並通過採用 UIViewRepresentable
協議使其可用於你的 SwiftUI 項目。 自 iOS 14 開始,Apple 為 SwiftUI 框架引入了一個名為TextEditor
的新組件。 這個 TextEditor
使開發者能夠在App中顯示和編輯多行文字。 在 iOS 16 中,Apple 進一步改進了內置的 TextField
以支持多行輸入。
在本章中,我們將詳細講解如何使用 TextEditor
以支援多行文字輸入。
如何使用 TextEditor
TextEditor
的使用方法並不複雜,可以說是非常容易。 你只需要一個狀態變數來存放輸入文字。 然後,在視圖的body
中建立 TextEditor
就可以了。下面是範例程式碼:
struct ContentView: View {
@State private var inputText = ""
var body: some View {
TextEditor(text: $inputText)
}
}
要使用 TextEditor
,你需要傳一個 inputText
的綁定,以便狀態變數可以儲存使用者的文字輸入。
你可以像任何 SwiftUI 視圖一樣客製編輯器的樣式。舉例,以下程式碼可以更改字體類型並調整文本編輯器的行距:
TextEditor(text: $inputText)
.font(.title)
.lineSpacing(20)
.autocapitalization(.words)
.disableAutocorrection(true)
.padding()
另外,你也可以選擇啟用/停用自動大寫和自動更正功能。
使用 onChange() 修飾器偵測文字輸入
在 UIKit 框架, UITextView
與 UITextViewDelegate
協議共同運作以處理文字輸入。 那麼,TextEditor
呢? 我們如何偵測使用者輸入的文字並對其進一步的處理?
SwiftUI 提供了一個 onChange()
修飾器,可以附加到 TextEditor
或任何其他視圖。 假設你正在使用 TextEditor
建立一個筆記App,並且需要實時顯示總字數。你可以將 onChange()
修飾器附加到 TextEditor
,如下所示:
struct ContentView: View {
@State private var inputText = ""
@State private var wordCount: Int = 0
var body: some View {
ZStack(alignment: .topTrailing) {
TextEditor(text: $inputText)
.font(.body)
.padding()
.padding(.top, 20)
.onChange(of: inputText) { value in
let words = inputText.split { $0 == " " || $0.isNewline }
self.wordCount = words.count
}
Text("\(wordCount) words")
.font(.headline)
.foregroundColor(.secondary)
.padding(.trailing)
}
}
}
在上面的程式碼中,我們宣告了一個 state 屬性來儲存字數。 另外,我們在 onChange()
修飾器中指定監測 inputText
的變化。 每當使用者輸入文字時, onChange()
修飾符內的程式碼就會被執行。 在閉包中,我們計算 inputText
中的單詞總數並相應地更新 wordCount
變數。
如果你在模擬器中運行App,應該會看到一個純文字編輯器。試試輸入幾字,編輯器就會實時顯示字數。
支援多行輸入、可擴展的文字欄
在 iOS 16 之前,內置的 TextField
只能支持單行文字輸入。 現在,Apple 大大改進了 TextField
視圖,允許使用者輸入多行文字。 更好的是,你現在可以使用一個名為 axis
的新參數來告訴 iOS 是否應該擴展文字欄。
例如,文字欄最初顯示單行輸入。 當使用者輸入文字時,文字欄便會自動擴展以支持多行輸入。 以下是範例程式碼:
struct TextFieldDemo: View {
@State private var comment = ""
var body: some View {
TextField("Comment", text: $comment, prompt: Text("Please input your comment"), axis: .vertical)
.padding()
.background(Color.green.opacity(0.2))
.cornerRadius(5.0)
.padding()
}
}
axis
參數的值可以是 .vertical
或 .horizontal
。 在上面的程式碼中,我們將值設置為.vertical
。 在這種情況下,文字欄會垂直擴展以支持多行輸入。 如果設置為 .horizontal
,文本字段將水平擴展並保持為單行文本字段。
通過配對 lineLimit
修飾器,你可以更改文字欄的初始大小。 比方說,如果要顯示一個三行文字,可以附加 lineLimit
修飾器並將值設置為 3
:
TextField("Comment", text: $comment, prompt: Text("Please input your comment"), axis: .vertical)
.lineLimit(3)
你也可以提供行限制的範圍。 以下是一個例子:
TextField("Comment", text: $comment, prompt: Text("Please input your comment"), axis: .vertical)
.lineLimit(3...5)
在這種情況下,文字欄就不會擴展超過 5 行。
總結
自 SwiftUI 首次發布以來,TextEditor
一直是最受期待的 UI 組件之一。 你現在可以使用這個原生組件來處理多行輸入。 隨著 iOS 16 的發布,你還可以使用 TextField
來靈活控制文字輸入的空間。 自動擴展功能使你可以輕鬆創建足夠靈活的文本字段以接受單行或多行輸入。
想更深入學習SwiftUI和下載完整程式碼?你可以從 AppCoda網站購買《精通 SwiftUI》完整電子版。