設定文字欄位

TextField 可讓使用者輸入及修改文字。您可以使用兩種類型的文字欄位:狀態導向文字欄位值導向文字欄位。選取要顯示內容的類型:

建議您使用狀態文字欄位,因為這類欄位可提供更完整且可靠的方式來管理 TextField 的狀態。下表列出這些類型文字欄位的差異,並說明以狀態為準的文字欄位提供的主要優勢:

功能

以價值為準文字欄位

狀態文字欄位

州福利

狀態管理

使用 onValueChange 回呼方法更新文字欄位狀態。您必須根據 onValueChange 回報的變更,更新自身狀態中的 value

明確使用 TextFieldState 物件來管理文字輸入狀態 (值、選取項目、組合)。系統可以記住並分享此狀態。

  • 已移除 onValueChange 回呼,以免您引入非同步行為。
  • 在重新組合、設定和程序終止後,狀態仍會保留。

視覺轉換

使用 VisualTransformation 修改顯示文字的顯示方式。這通常會在單一步驟中處理輸入和輸出格式。

使用 InputTransformation 修改使用者輸入內容,然後再提交至狀態;使用 OutputTransformation 設定文字欄位內容格式,但不變更基礎狀態資料。

  • 您不再需要使用 OutputTransformation 提供原始原始文字與轉換文字之間的偏移對應項目。

線條限制

接受 singleLine: Boolean, maxLines: IntminLines: Int 來控制行數。

使用 lineLimits: TextFieldLineLimits 設定文字欄位可占用的行數下限和上限。

  • 提供 TextFieldLineLimits 類型的 lineLimits 參數,消除設定線條限制時的模糊性。

安全文字欄位

SecureTextField 是建構在狀態文字欄位之上的可組合函式,用於輸入密碼欄位。

  • 讓您在幕後進行安全性最佳化,並提供預先定義的 UI 和 textObfuscationMode

本頁面說明如何實作 TextField、樣式 TextField 輸入內容,以及設定其他 TextField 選項,例如鍵盤選項和視覺轉換使用者輸入內容。

選擇 TextField 實作

TextField 實作分為兩個層級:

  1. TextField 為 Material Design 實作。建議您選擇此實作程序,因為符合Material Design 設計準則
    • 預設樣式為「填入」
    • OutlinedTextField外框樣式版本
  2. BasicTextField 可讓使用者透過硬體或軟體鍵盤編輯文字,但無法提供提示或預留位置等裝飾。

TextField(
    state = rememberTextFieldState(initialText = "Hello"),
    label = { Text("Label") }
)

含有「

OutlinedTextField(
    state = rememberTextFieldState(),
    label = { Text("Label") }
)

可編輯文字欄位,帶有紫色邊框和標籤。

樣式 TextField

TextFieldBasicTextField 共用許多常見的參數,可用於自訂。TextField 原始碼內提供 TextField 的完整清單。以下列舉部分有用參數的內容:

  • textStyle
  • lineLimits

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

多行 TextField,包含可編輯的兩行加上標籤

如果設計需要 Material TextFieldOutlinedTextField,建議使用 TextField 而非 BasicTextField。然而,如果建構的設計不需要使用材質規格的裝飾,則應使用 BasicTextField

使用 Brush API 設定輸入樣式

您可以使用 Brush APITextField 中套用更進階的樣式。以下章節將說明如何使用筆刷將彩色漸層新增至 TextField 輸入內容。

如要進一步瞭解如何使用 Brush API 設定文字樣式,請參閱「使用 Brush API 啟用進階樣式」。

使用 TextStyle 實作彩色漸層

如要在 TextField 中輸入文字時導入彩色漸層,請將所選的筆刷設為 TextFieldTextStyle。在本範例中,我們使用內建的筆刷搭配 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)
)

使用 buildAnnotatedString 和 SpanStyle 搭配 linearGradient,只自訂某段文字。
圖 1. TextField 內容的彩虹漸層效果。

管理文字欄位狀態

TextField 會使用名為 TextFieldState 的專屬狀態容器類別,用於其內容和目前的選取項目。TextFieldState 的設計目的是在架構中適當的位置提升。TextFieldState 提供 2 個主要屬性:

  • initialTextTextField 的內容。
  • 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,
)

文字欄位內顯示「Username」文字的 TextField。
圖 2. TextField,其中「Username」為初始文字。

使用 TextFieldBuffer 修改文字

TextFieldBuffer 是可編輯的文字容器,功能類似 StringBuilder。它會同時保留文字內容和目前選取項目的相關資訊。

您經常會在 TextFieldState.editInputTransformation.transformInputOutputTransformation.transformOutput 等函式中,看到 TextFieldBuffer 做為接收器範圍。在這些函式中,您可以視需要讀取或更新 TextFieldBuffer。之後,這些變更會提交至 TextFieldState,或是在 OutputTransformation 的情況下傳遞至轉譯管道。

您可以使用標準編輯函式 (例如 appendinsertreplacedelete) 修改緩衝區的內容。如要變更選取狀態,請直接設定其 selection: TextRange 變數,或使用 placeCursorAtEndselectAll 等公用函式。選取項目本身由 TextRange 表示,其中起始索引包含起始值,結束索引則不包含結束值。TextRange 的起始和結束值相同 (例如 (3, 3)),表示游標位置目前沒有選取任何字元。

val phoneNumberState = rememberTextFieldState()

LaunchedEffect(phoneNumberState) {
    phoneNumberState.edit { // TextFieldBuffer scope
        append("123456789")
    }
}

TextField(
    state = phoneNumberState,
    inputTransformation = InputTransformation { // TextFieldBuffer scope
        if (asCharSequence().isDigitsOnly()) {
            revertAllChanges()
        }
    },
    outputTransformation = OutputTransformation {
        if (length > 0) insert(0, "(")
        if (length > 4) insert(4, ")")
        if (length > 8) insert(8, "-")
    }
)

TextFieldState 中編輯文字

您可以透過多種方法,直接透過狀態變數編輯狀態:

  • edit:可讓您編輯狀態內容,並提供 TextFieldBuffer 函式,讓您使用 insertreplaceappend 等方法。

    val usernameState = rememberTextFieldState("I love Android")
    // textFieldState.text : I love Android
    // textFieldState.selection: TextRange(14, 14)
    usernameState.edit { insert(14, "!") }
    // textFieldState.text : I love Android!
    // textFieldState.selection: TextRange(15, 15)
    usernameState.edit { replace(7, 14, "Compose") }
    // textFieldState.text : I love Compose!
    // textFieldState.selection: TextRange(15, 15)
    usernameState.edit { append("!!!") }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(18, 18)
    usernameState.edit { selectAll() }
    // textFieldState.text : I love Compose!!!!
    // textFieldState.selection: TextRange(0, 18)

  • setTextAndPlaceCursorAtEnd:清除目前的文字,並以指定的文字取代,然後將游標設為結尾。

    usernameState.setTextAndPlaceCursorAtEnd("I really love Android")
    // textFieldState.text : I really love Android
    // textFieldState.selection : TextRange(21, 21)

  • clearText:清除所有文字。

    usernameState.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 (!TextUtils.isDigitsOnly(asCharSequence())) {
            revertAllChanges()
        }
    }
}

連結輸入轉換

如要在文字輸入內容上新增多個篩選器,請使用 then 擴充功能函式連結 InputTransformation。系統會依序執行篩選器。最佳做法是先套用最具選擇性的篩選器,避免對最終會遭到篩除的資料進行不必要的轉換。

TextField(
    state = rememberTextFieldState(),
    inputTransformation = InputTransformation.maxLength(6)
        .then(CustomInputTransformation()),
)

新增輸入轉換後,TextField 輸入內容最多可接受 10 位數。

在輸入內容顯示前先格式化

OutputTransformation 可讓您在使用者輸入內容顯示在螢幕上之前,先對其格式化。與 InputTransformation 不同,透過 OutputTransformation 完成的格式設定不會儲存在 TextFieldState 中。以先前的電話號碼範例為例,您需要在適當的位置加入括號和破折號:

美國電話號碼,格式正確,並使用括號、連字號和對應的索引。
圖 3. 美國電話號碼,格式正確且有對應的索引。

這是在以值為基礎的 TextField 中處理 VisualTransformation 的更新方式,主要差異在於您不必計算其偏移對應項目。

OutputTransformation 是單一抽象方法介面。如要實作自訂 OutputTransformation,您必須覆寫 transformOutput 方法:

class CustomOutputTransformation : OutputTransformation {
    override fun TextFieldBuffer.transformOutput() {
    }
}

如要設定電話號碼格式,請在 OutputTransformation 的索引 0 處新增開方括號,在索引 4 處新增結束方括號,並在索引 8 處新增破折號:

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

轉換作業的搭配運作方式

下圖顯示從文字輸入到轉換至輸出內容的流程:

這張圖表顯示文字輸入內容如何經過轉換,最後成為文字輸出內容。
圖 4. 圖表顯示文字輸入內容如何經過轉換,最後成為文字輸出內容。
  1. 從輸入來源接收輸入內容。
  2. 輸入內容會透過 InputTransformation 進行篩選,並儲存在 TextFieldState 中。
  3. 輸入內容會傳遞至 OutputTransformation 進行格式設定。
  4. 輸入內容會顯示在 TextField 中。

設定鍵盤選項

TextField 可讓您設定鍵盤設定選項 (例如鍵盤配置);或是啟用自動更正功能 (如果鍵盤有支援)。如果螢幕鍵盤不符合此處提供的選項,則可能無法保證某些選項可以使用。以下是支援的鍵盤選項清單:

  • capitalization
  • autoCorrect
  • keyboardType
  • imeAction

其他資源