사용자 입력 처리

TextField를 사용하면 사용자가 텍스트를 입력하고 수정할 수 있습니다. 이 페이지에서는 TextField를 구현하고 TextField 입력의 스타일을 지정하며 키보드 옵션 및 사용자 입력을 시각적으로 변환하는 등 다른 TextField 옵션을 구성하는 방법을 설명합니다.

TextField 구현 선택

TextField 구현에는 두 가지 수준이 있습니다.

  1. TextField는 머티리얼 디자인 구현입니다. 이 구현은 Material Design 가이드라인을 따르므로 이 구현을 선택하는 것이 좋습니다.
  2. BasicTextField를 사용하면 사용자가 하드웨어 또는 소프트웨어 키보드를 통해 텍스트를 수정할 수 있지만 힌트나 자리표시자와 같은 장식은 제공하지 않습니다.

@Composable
fun SimpleFilledTextFieldSample() {
    var text by remember { mutableStateOf("Hello") }

    TextField(
        value = text,
        onValueChange = { text = it },
        label = { Text("Label") }
    )
}

'Hello'라는 단어가 포함된 수정 가능한 텍스트 입력란

@Composable
fun SimpleOutlinedTextFieldSample() {
    var text by remember { mutableStateOf("") }

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

보라색 테두리와 라벨이 있는 수정 가능한 텍스트 입력란.

스타일 TextField

TextFieldBasicTextField는 맞춤설정할 수 있는 많은 공통 매개변수를 공유합니다. TextField의 전체 목록은 TextField 소스 코드에서 확인할 수 있습니다. 다음은 유용한 매개변수의 일부 목록입니다.

  • singleLine
  • maxLines
  • textStyle

@Composable
fun StyledTextField() {
    var value by remember { mutableStateOf("Hello\nWorld\nInvisible") }

    TextField(
        value = value,
        onValueChange = { value = it },
        label = { Text("Enter text") },
        maxLines = 2,
        textStyle = TextStyle(color = Color.Blue, fontWeight = FontWeight.Bold),
        modifier = Modifier.padding(20.dp)
    )
}

여러 줄의 TextField, 수정 가능한 두 줄과 라벨이 있음

디자인에 Material TextField 또는 OutlinedTextField가 필요한 경우 BasicTextField보다 TextField를 사용하는 것이 좋습니다. 그러나 머티리얼 사양의 장식이 필요하지 않은 디자인을 빌드할 때는 BasicTextField을 사용해야 합니다.

Brush API를 사용한 스타일 입력

Brush API를 사용하여 TextField에서 고급 스타일을 지정할 수 있습니다. 다음 섹션에서는 브러시를 사용하여 TextField 입력에 색상 그라데이션을 추가하는 방법을 설명합니다.

Brush API를 사용하여 텍스트 스타일을 지정하는 방법에 관한 자세한 내용은 Brush API로 고급 스타일 지정 사용 설정을 참고하세요.

TextStyle를 사용하여 색상 그라디언트 구현

TextField 내에서 입력할 때 색상 그라데이션을 구현하려면 원하는 브러시를 TextFieldTextStyle로 설정합니다. 이 예에서는 linearGradient와 함께 내장 브러시를 사용하여 TextField에 텍스트를 입력할 때 무지개 그라데이션 효과를 확인합니다.

var text by remember { mutableStateOf("") }
val brush = remember {
    Brush.linearGradient(
        colors = rainbowColors
    )
}
TextField(
    value = text, onValueChange = { text = it }, textStyle = TextStyle(brush = brush)
)

buildAnnotatedString 및 SpanStyle을 linearGradient와 함께 사용하여 텍스트 일부만 맞춤설정합니다.
그림 3. linearGradient와 함께 buildAnnotatedStringSpanStyle를 사용하여 텍스트 일부만 맞춤설정합니다.

키보드 옵션 설정

TextField를 사용하면 키보드 레이아웃과 같은 키보드 구성 옵션을 설정하거나 키보드에서 지원하는 경우 자동 수정을 사용 설정할 수 있습니다. 소프트웨어 키보드가 여기에 제공된 옵션을 준수하지 않을 경우 일부 옵션이 보장되지 않을 수도 있습니다. 다음은 지원되는 키보드 옵션의 목록입니다.

  • capitalization
  • autoCorrect
  • keyboardType
  • imeAction

형식 입력

TextField를 사용하면 입력 값에 VisualTransformation을 설정할 수 있습니다. 예를 들어 비밀번호를 나타내는 문자를 * 기호로 바꾸거나 신용카드 번호의 4자리마다 하이픈을 삽입할 수 있습니다.

@Composable
fun PasswordTextField() {
    var password by rememberSaveable { mutableStateOf("") }

    TextField(
        value = password,
        onValueChange = { password = it },
        label = { Text("Enter password") },
        visualTransformation = PasswordVisualTransformation(),
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password)
    )
}

비밀번호 텍스트 입력란, 텍스트는 가려짐

VisualTransformationSamples 소스 코드에서 더 많은 예를 확인할 수 있습니다.

입력 정리

텍스트를 수정할 때 일반적인 작업은 변경 시 선행 문자를 제거하거나 입력 문자열을 변환하는 것입니다.

모델에서는 키보드가 임의 및 대규모로 onValueChange를 각각 수정할 수 있다고 가정합니다. 예를 들어 사용자가 자동 수정을 사용하거나, 단어를 그림 이모티콘으로 대체하거나, 그 밖의 스마트 편집 기능이 있는 경우 이러한 상황이 발생할 수 있습니다. 이를 올바르게 처리하려면 onValueChange에 전달된 현재 텍스트가 onValueChange에 전달될 이전 또는 다음 값과 관련이 없다는 가정 하에 모든 변환 로직을 작성합니다.

앞의 0을 허용하지 않는 텍스트 입력란을 구현하려면 모든 값을 변경할 때 선행 0을 전부 제거하면 됩니다.

@Composable
fun NoLeadingZeroes() {
    var input by rememberSaveable { mutableStateOf("") }
    TextField(
        value = input,
        onValueChange = { newText ->
            input = newText.trimStart { it == '0' }
        }
    )
}

텍스트를 정리하는 동안 커서 위치를 제어하려면 상태의 일부로 TextFieldTextFieldValue 오버로드를 사용하세요.

상태 관련 권장사항

다음은 앱에서 입력 문제를 방지하기 위해 TextField 상태를 정의하고 업데이트하는 일련의 권장사항입니다.

  • MutableState를 사용하여 TextField 상태 나타내기: StateFlow와 같은 반응형 스트림을 사용하여 TextField 상태를 나타내지 마세요. 이러한 구조는 비동기 지연을 일으킬 수 있습니다.

class SignUpViewModel : ViewModel() {

    var username by mutableStateOf("")
        private set

    /* ... */
}

  • 상태 업데이트 지연 방지: onValueChange를 호출할 때 TextField를 동기식으로 즉시 업데이트합니다.

// SignUpViewModel.kt

class SignUpViewModel(private val userRepository: UserRepository) : ViewModel() {

    var username by mutableStateOf("")
        private set

    fun updateUsername(input: String) {
        username = input
    }
}

// SignUpScreen.kt

@Composable
fun SignUpScreen(/*...*/) {

    OutlinedTextField(
        value = viewModel.username,
        onValueChange = { username -> viewModel.updateUsername(username) }
        /*...*/
    )
}

  • 상태를 정의할 위치: 입력할 때 TextField 상태에 비즈니스 로직 유효성 검사가 필요한 경우 상태를 ViewModel로 호이스팅하는 것이 맞습니다. 그렇지 않은 경우 컴포저블 또는 상태 홀더 클래스를 정보 소스로 사용할 수 있습니다. 상태를 호이스팅할 위치에 관한 자세한 내용은 상태 호이스팅 문서를 참고하세요.