Android Compose UI TextField 輸入框與鍵盤處理

輸入框是讓使用者輸入文字的元件。Compose 提供了兩種主要風格:TextField (Material 預設樣式) 與 BasicTextField (無樣式,完全自定義)。

基礎用法

TextField 必須遵循狀態提升 (State Hoisting) 模式。它不會自己儲存文字,你需要將變數傳給它。

var text by remember { mutableStateOf("") }

TextField(
    value = text,
    onValueChange = { newText -> text = newText },
    label = { Text("請輸入姓名") },
    placeholder = { Text("例如:王小明") },
    leadingIcon = { Icon(Icons.Default.Person, contentDescription = null) },
    isError = text.length > 10, // 錯誤狀態
    singleLine = true
)

OutlinedTextField

這是另一種常見的樣式,只有外框。

OutlinedTextField(
    value = text,
    onValueChange = { text = it },
    label = { Text("Email") }
)

鍵盤選項 (KeyboardOptions)

我們可以設定鍵盤的類型 (Type) 與右下角按鈕的行為 (ImeAction)。

TextField(
    value = text,
    onValueChange = { text = it },
    keyboardOptions = KeyboardOptions(
        keyboardType = KeyboardType.Email, // Email 鍵盤
        imeAction = ImeAction.Send // 顯示 "傳送" 按鈕
    ),
    keyboardActions = KeyboardActions(
        onSend = { 
            // 處理傳送事件
            performSend()
        }
    )
)

常見的 KeyboardType:

  • Text (預設)
  • Number (數字)
  • Email (顯示 @)
  • Password (隱藏文字,需搭配 visualTransformation)
  • Phone (電話)

密碼輸入框

要隱藏輸入的文字,需要設定 visualTransformation

var password by remember { mutableStateOf("") }
var passwordVisible by remember { mutableStateOf(false) }

TextField(
    value = password,
    onValueChange = { password = it },
    label = { Text("Password") },
    visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
    keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
    trailingIcon = {
        val image = if (passwordVisible) Icons.Filled.Visibility else Icons.Filled.VisibilityOff
        IconButton(onClick = { passwordVisible = !passwordVisible }) {
            Icon(imageVector = image, contentDescription = null)
        }
    }
)

焦點控制 (Focus Requester)

有時候我們需要用程式碼控制焦點(例如進入畫面自動彈出鍵盤,或按 Enter 跳到下一個輸入框)。

val focusRequester = remember { FocusRequester() }

TextField(
    value = text,
    onValueChange = { text = it },
    modifier = Modifier.focusRequester(focusRequester)
)

// 自動取得焦點
LaunchedEffect(Unit) {
    focusRequester.requestFocus()
}

小結

  • 使用 TextFieldOutlinedTextField
  • 透過 KeyboardOptions 優化輸入體驗。
  • 使用 VisualTransformation 處理密碼顯示。