TextField 可讓使用者輸入及修改文字。您可以使用兩種文字欄位:以狀態為準的文字欄位和以值為準的文字欄位。選取要顯示內容的類型:
建議使用以狀態為基礎的文字欄位,因為這種做法更完整可靠,有助於管理 TextField 的狀態。下表列出這些文字欄位的差異,並說明狀態型文字欄位的主要優點:
功能 |
以值為準的文字欄位 |
州別文字欄位 |
州別福利 |
|---|---|---|---|
狀態管理 |
使用 |
明確使用 |
|
視覺化轉換 |
使用 |
使用 |
|
行數限制 |
接受 |
使用 |
|
安全文字欄位 |
無 |
|
|
本頁面說明如何實作 TextField、設定 TextField 輸入內容的樣式,以及設定其他 TextField 選項,例如鍵盤選項和以視覺化方式轉換使用者輸入內容。
選擇 TextField 實作方式
TextField 實作分為兩個層級:
TextField為質感設計實作。建議您選擇此實作程序,因為符合質感設計準則:- 預設樣式為「已填入」
OutlinedTextField是外框樣式版本
BasicTextField可讓使用者透過硬體或軟體鍵盤編輯文字,但無法提供提示或預留位置等裝飾。
TextField( state = rememberTextFieldState(initialText = "Hello"), label = { Text("Label") } )
OutlinedTextField( state = rememberTextFieldState(), label = { Text("Label") } )
樣式 TextField
TextField 和 BasicTextField 會共用許多常見的參數以進行自訂。TextField 原始碼內提供 TextField 的完整清單。這份清單僅列舉部分有用參數的內容:
textStylelineLimits
TextField( state = rememberTextFieldState("Hello\nWorld\nInvisible"), lineLimits = TextFieldLineLimits.MultiLine(maxHeightInLines = 2), placeholder = { Text("") }, textStyle = TextStyle(color = Color.Blue, fontWeight = FontWeight.Bold), label = { Text("Enter text") }, modifier = Modifier.padding(20.dp) )
如果設計需要 Material TextField 或 OutlinedTextField,建議使用 BasicTextField 而非 TextField。然而,如果建構的設計不需要使用 Material 規格的裝飾,則應使用 BasicTextField。
設定行數限制
TextField 可組合函式支援沿單一軸捲動。捲動行為取決於 lineLimits 參數。單行 TextField 會水平捲動,多行 TextField 則會垂直捲動。
使用 TextFieldLineLimits 選擇適合你裝置的線路設定:TextField
TextField( state = rememberTextFieldState(), lineLimits = TextFieldLineLimits.SingleLine )
SingleLine 設定具有下列特性:
- 文字不會換行,也不允許換行。
TextField的高度一律固定。- 如果文字溢位,系統會水平捲動。
TextField( state = rememberTextFieldState("Hello\nWorld\nHello\nWorld"), lineLimits = TextFieldLineLimits.MultiLine(1, 4) )
MultiLine 設定具有下列特性:
- 接受兩個參數:
minHeightInLines和maxHeightInLines。 - 文字欄位至少要有
minHeightInLines高。 - 如果文字溢位,系統會自動換行。
- 如果文字需要更多行,欄位會擴大,直到達到
maxHeightInLines高度,並垂直捲動。
使用 Brush API 設定輸入內容的樣式
您可以在 TextField 中使用 Brush API,進行更進階的樣式設定。下一節說明如何使用 Brush 在 TextField 輸入內容中新增彩色漸層。
如要進一步瞭解如何使用 Brush API 設定文字樣式,請參閱「使用 Brush API 啟用進階樣式設定」。
使用 TextStyle 實作彩色漸層
如要在 TextField 中輸入文字時實作彩色漸層,請將所選筆刷設為 TextField 的 TextStyle。在本範例中,我們使用內建筆刷和 linearGradient,在 TextField 中輸入文字時,檢視彩虹漸層效果。
val brush = remember { Brush.linearGradient( colors = listOf(Color.Red, Color.Yellow, Color.Green, Color.Blue, Color.Magenta) ) } TextField( state = rememberTextFieldState(), textStyle = TextStyle(brush = brush) )

TextField 內容的彩虹漸層效果。管理文字欄位狀態
TextField 會使用名為 TextFieldState 的專屬狀態容器類別,處理內容和選取項目。TextFieldState 的設計宗旨是盡可能提升架構的適用性。TextFieldState 提供的主要屬性有 2 種:
initialText:TextField的內容。initialSelection:指出游標或選取範圍所在位置。
TextFieldState 與其他方法 (例如 onValueChange 回呼) 的不同之處在於,TextFieldState 會完整封裝整個輸入流程。包括使用正確的支援資料結構、內嵌篩選器和格式化工具,以及同步處理來自不同來源的所有編輯內容。
您可以使用 TextFieldState() 在 TextField 中提升狀態。為此,我們建議使用 rememberTextFieldState() 函式。rememberTextFieldState() 會在可組合項中建立 TextFieldState 例項,確保系統會記住狀態物件,並提供內建的儲存和還原功能:
val usernameState = rememberTextFieldState() TextField( state = usernameState, lineLimits = TextFieldLineLimits.SingleLine, placeholder = { Text("Enter Username") } )
rememberTextFieldState 可以有空白參數,也可以傳遞初始值,代表初始化時的文字值。如果在後續重組中傳遞不同的值,狀態值就不會更新。如要在初始化後更新狀態,請對 TextFieldState 呼叫編輯方法。
TextField( state = rememberTextFieldState(initialText = "Username"), lineLimits = TextFieldLineLimits.SingleLine, )
TextField,且初始文字為「使用者名稱」。使用 TextFieldBuffer 修改文字
TextFieldBuffer 可做為可編輯的文字容器,功能類似於 StringBuilder。其中包含文字內容和選取範圍的相關資訊。
您經常會遇到 TextFieldBuffer 做為函式 (例如 TextFieldState.edit、InputTransformation.transformInput 或 OutputTransformation.transformOutput) 的接收器範圍。在這些函式中,您可以視需要讀取或更新 TextFieldBuffer。之後,這些變更會提交至 TextFieldState,或在 OutputTransformation 的情況下傳遞至算繪管道。
你可以使用 append、insert、replace 或 delete 等標準編輯函式修改緩衝區內容。如要變更選取狀態,可以直接設定 selection: TextRange 變數,也可以使用 placeCursorAtEnd 或 selectAll 等公用程式函式。選取範圍本身以 TextRange 表示,其中包含開始索引,但不包含結束索引。如果 TextRange 的起始值和結束值相同 (例如 (3, 3)),表示游標位置未選取任何字元。
val phoneNumberState = rememberTextFieldState("1234567890") TextField( state = phoneNumberState, keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Phone ), inputTransformation = InputTransformation.maxLength(10).then { if (!asCharSequence().isDigitsOnly()) { revertAllChanges() } }, outputTransformation = OutputTransformation { if (length > 0) insert(0, "(") if (length > 4) insert(4, ")") if (length > 8) insert(8, "-") } )
編輯「TextFieldState」中的文字
您可以透過幾種方法,直接透過狀態變數編輯狀態:
edit:可讓您編輯狀態內容,並提供TextFieldBuffer函式,方便您使用insert、replace、append等方法。// Initial textFieldState text passed in is "I love Android" // textFieldState.text : I love Android // textFieldState.selection: TextRange(14, 14) textFieldState.edit { insert(14, "!") } // textFieldState.text : I love Android! // textFieldState.selection: TextRange(15, 15) textFieldState.edit { replace(7, 14, "Compose") } // textFieldState.text : I love Compose! // textFieldState.selection: TextRange(15, 15) textFieldState.edit { append("!!!") } // textFieldState.text : I love Compose!!!! // textFieldState.selection: TextRange(18, 18) textFieldState.edit { selectAll() } // textFieldState.text : I love Compose!!!! // textFieldState.selection: TextRange(0, 18)
setTextAndPlaceCursorAtEnd:清除目前的文字、以指定文字取代,並將游標設在結尾。textFieldState.setTextAndPlaceCursorAtEnd("I really love Android") // textFieldState.text : I really love Android // textFieldState.selection : TextRange(21, 21)
clearText:清除所有文字。textFieldState.clearText() // textFieldState.text : // textFieldState.selection : TextRange(0, 0)
如要瞭解其他 TextFieldState 函式,請參閱 TextFieldState 參考資料。
修改使用者輸入內容
以下各節說明如何修改使用者輸入內容。輸入內容轉換可讓您在使用者輸入內容時進行篩選,而輸出內容轉換則會在使用者輸入內容顯示在畫面上前,先進行格式化。TextField
使用輸入轉換功能篩選使用者輸入內容
輸入轉換功能可讓您篩選使用者輸入內容。舉例來說,如果 TextField 接受美國電話號碼,您只會接受 10 位數。InputTransformation 的結果會儲存在 TextFieldState 中。
系統內建的篩選器可滿足常見的InputTransformation用途。如要限制長度,請呼叫 InputTransformation.maxLength():
TextField( state = rememberTextFieldState(), lineLimits = TextFieldLineLimits.SingleLine, inputTransformation = InputTransformation.maxLength(10) )
自訂輸入轉換
InputTransformation 是單一函式介面。實作自訂 InputTransformation 時,您需要覆寫 TextFieldBuffer.transformInput:
class CustomInputTransformation : InputTransformation { override fun TextFieldBuffer.transformInput() { } }
如果是電話號碼,請新增自訂輸入轉換,只允許在 TextField 中輸入數字:
class DigitOnlyInputTransformation : InputTransformation { override fun TextFieldBuffer.transformInput() { if (!asCharSequence().isDigitsOnly()) { revertAllChanges() } } }
鏈結輸入轉換
如要在文字輸入內容中新增多個篩選器,請使用 then 擴充功能函式,將 InputTransformation 串連在一起。系統會依序執行篩選器。按照最佳做法,請先套用最嚴格的篩選器,避免對最終會篩除的資料進行不必要的轉換。
TextField( state = rememberTextFieldState(), inputTransformation = InputTransformation.maxLength(6) .then(CustomInputTransformation()), )
新增輸入轉換後,TextField 輸入內容最多可接受 10 位數。
在顯示前格式化輸入內容
OutputTransformation 可讓您在使用者輸入內容顯示於畫面前,先將其格式化。與 InputTransformation 不同,透過 OutputTransformation 完成的格式設定不會儲存在 TextFieldState 中。以上一個電話號碼範例為基礎,您需要在適當位置新增半形括號和破折號:
這是處理以值為基礎的 VisualTransformation TextField 的更新方式,主要差異在於您不必計算其偏移對應。
OutputTransformation 是單一抽象方法介面。如要實作自訂 OutputTransformation,您需要覆寫 transformOutput 方法:
class CustomOutputTransformation : OutputTransformation { override fun TextFieldBuffer.transformOutput() { } }
如要設定電話號碼格式,請在索引 0 新增左括號、在索引 4 新增右括號,並在索引 8 新增破折號至 OutputTransformation:
class PhoneNumberOutputTransformation : OutputTransformation { override fun TextFieldBuffer.transformOutput() { if (length > 0) insert(0, "(") if (length > 4) insert(4, ")") if (length > 8) insert(8, "-") } }
接著,將 OutputTransformation 新增至 TextField:
TextField( state = rememberTextFieldState(), outputTransformation = PhoneNumberOutputTransformation() )
轉換如何搭配運作
下圖顯示從文字輸入到轉換再到輸出的流程:
- 從輸入來源接收輸入內容。
- 輸入內容會透過
InputTransformation篩選,並儲存在 TextFieldState 中。 - 輸入內容會透過
OutputTransformation進行格式化。 - 輸入內容會顯示在
TextField中。
設定鍵盤選項
TextField 可讓您設定鍵盤設定選項 (例如鍵盤配置);或是啟用自動更正功能 (如果鍵盤有支援)。如果螢幕鍵盤不符合此處提供的選項,則可能無法保證某些選項可以使用。以下是支援的鍵盤選項清單:
capitalizationautoCorrectkeyboardTypeimeAction
KeyboardOptions 類別現在包含新的布林值參數 showKeyboardOnFocus,專門用於與 TextFieldState 整合的 TextField 元件。當 TextField 透過直接使用者互動以外的方式 (例如以程式輔助方式) 取得焦點時,軟體鍵盤的行為會受這個選項控管。
如果 KeyboardOptions.showKeyboardOnFocus 設為 true,且 TextField 間接取得焦點,軟體鍵盤就不會自動顯示。在這種情況下,使用者必須明確輕觸 TextField 本身,才能顯示鍵盤。
定義鍵盤互動邏輯
Android 軟體鍵盤上的動作按鈕可讓使用者在應用程式中進行互動式回覆。如要進一步瞭解如何設定動作按鈕,請參閱「設定鍵盤選項」一節。
如要定義使用者輕觸這個動作按鈕時會發生的情況,請使用 onKeyboardAction 參數。這個參數接受名為 KeyboardActionHandler 的選用函式介面。KeyboardActionHandler 介面包含單一方法 onKeyboardAction(performDefaultAction: () -> Unit)。提供這個 onKeyboardAction 方法的實作方式,即可導入自訂邏輯,在使用者按下鍵盤的動作按鈕時執行。
多種標準鍵盤動作類型都內建預設行為。
舉例來說,選取 ImeAction.Next 或 ImeAction.Previous 做為動作類型時,焦點預設會分別移至後續或先前的輸入欄位。同樣地,如果動作按鈕設為 ImeAction.Done,通常會關閉軟體鍵盤。這些預設功能會自動執行,您不需要提供 KeyboardActionHandler。
除了這些預設動作,您也可以實作自訂行為。
提供 KeyboardActionHandler 時,其 onKeyboardAction 方法會收到 performDefaultAction 函式。您可以在自訂邏輯中的任何時間點呼叫這個 performDefaultAction() 函式,藉此觸發與目前 IME 動作相關聯的標準預設行為。
TextField( state = textFieldViewModel.usernameState, keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), onKeyboardAction = { performDefaultAction -> textFieldViewModel.validateUsername() performDefaultAction() } )
這個程式碼片段說明註冊畫面上的常見用途,其中包含使用者名稱欄位。這個欄位會選取 ImeAction.Next 做為鍵盤動作按鈕。選取這個選項後,系統會快速流暢地導覽至下一個密碼欄位。
除了這個標準導覽功能外,您還必須在使用者輸入密碼時,啟動使用者名稱的背景驗證程序。為確保 ImeAction.Next 固有的預設焦點切換行為與這項自訂驗證邏輯一併保留,系統會叫用 performDefaultAction() 函式。呼叫 performDefaultAction() 會隱含地觸發基礎焦點管理系統,將焦點移至下一個適當的 UI 元素,保留預期的導覽流程。
建立安全密碼欄位
SecureTextField 是以狀態型文字欄位為基礎建構的可組合項,用於撰寫密碼欄位。建議使用 SecureTextField 建立密碼文字欄位,因為這項函式預設會隱藏輸入的字元,並停用剪下和複製動作。
SecureTextField 具有 textObfuscationMode,可控制使用者查看字元輸入的方式。textObfuscationMode 提供下列選項:
Hidden:隱藏所有輸入內容。桌上型電腦平台的預設行為。
Visible:顯示所有輸入內容。
RevealLastTyped:隱藏所有輸入內容,只顯示最後一個字元。行動裝置上的預設行為。