검색이나 값을 사용자로부터 입력받아야 하는 경우 xml에서는 EditText를 사용해 왔습니다.
Compose에서는 TextField라는 것을 사용합니다.
TextField는 어떻게 커스텀할 수 있을까요?
1. TextField
먼저, TextField에 대해 간단히 알아보도록 하겠습니다.
@Composable
fun TextField(
value: TextFieldValue,
onValueChange: (TextFieldValue) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = LocalTextStyle.current,
label: @Composable (() -> Unit)? = null,
placeholder: @Composable (() -> Unit)? = null,
leadingIcon: @Composable (() -> Unit)? = null,
trailingIcon: @Composable (() -> Unit)? = null,
isError: Boolean = false,
visualTransformation: VisualTransformation = VisualTransformation.None,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions(),
singleLine: Boolean = false,
maxLines: Int = Int.MAX_VALUE,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
shape: Shape = TextFieldDefaults.TextFieldShape,
colors: TextFieldColors = TextFieldDefaults.textFieldColors()
)
EditText와 비슷하게 placeholder, enabled, maxLines 등 다양한 기능을 제공합니다.
TextField는 위 사진처럼 Material 디자인을 기본으로 하기 때문에 다양한 모양의 TextField를 표현하기에는 제한적입니다.
그렇다면 커스텀해야 하는 경우 어떻게 해야 할까요?
바로 foundation 아티팩트에 위치한 BasicTextField를 사용하여 다양하게 커스텀할 수 있습니다.
2. BasicTextField
BasicTextField 내부 코드를 살펴보도록 하겠습니다.
@Composable
fun BasicTextField(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = TextStyle.Default,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
singleLine: Boolean = false,
maxLines: Int = Int.MAX_VALUE,
visualTransformation: VisualTransformation = VisualTransformation.None,
onTextLayout: (TextLayoutResult) -> Unit = {},
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
cursorBrush: Brush = SolidColor(Color.Black),
decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit =
@Composable { innerTextField -> innerTextField() }
)
TextField와 크게 다르지 않지만 placeholder나 label 등은 보이지 않는 것을 보아 제공하지 않는 것을 확인할 수 있습니다.
하지만 맨 밑에 새롭게 추가된 인자도 있습니다. 바로 decorationBox인데요,
커스텀 하고 싶은 UI를 decorationBox에 구현할 수 있습니다!
그럼 간단한 예제와 함께 확인해 보도록 하겠습니다.
decorationBox = { innerTextField ->
Row(
modifier = Modifier
.padding(horizontal = 64.dp)
.fillMaxWidth()
.background(color = Color(0xFFD2F3F2), shape = RoundedCornerShape(size = 16.dp))
.padding(all = 16.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = Icons.Default.Search,
contentDescription = "",
tint = Color.DarkGray,
)
Spacer(modifier = Modifier.width(width = 8.dp))
innerTextField()
}
},
현재 decorationBox안을 보면, 텍스트를 입력할 수 있는 박스와 아이콘이 있도록 구현되어 있습니다. 그리고 decorationBox의 기본 인자인 innerTextField()를 마지막 줄에 적어주었습니다. innerTextField는 키보드 커서를 표시할 수 있도록 해주기 때문에 작성하지 않는 경우에는 키보드 커서가 노출되지 않습니다.
아래 결과물은 다음과 같습니다!
위에서 말했듯이 BasicTextField에는 placeholder 인자가 존재하지 않습니다. placeholder를 넣어주고 싶은 경우에는 어떻게 해야 할까요?
if (value.isEmpty()) {
Text(
text = "placeholder",
fontSize = 18.sp,
color = Color.LightGray,
)
}
위 코드처럼 textField안에 값이 비었는지 확인하여 간단하게 넣어줄 수 있습니다!
이제 다양한 디자인의 TextField를 구현해야 한다면 BasicTextField를 활용해 보는 것이 어떨까요?!😀😀
'Android' 카테고리의 다른 글
[Android] EditText에 InputFilter 적용이 안될 때 (25) | 2023.09.13 |
---|---|
[Android] Jetpack Compose에서 Toast Message를 Custom 할 수 있을까? (0) | 2023.06.19 |
[Android] 화면 터치 여부를 작동하는 dispatchTouchEvent는 어떻게 작동할까 (0) | 2023.05.24 |
[Android] Jetpack Compose로 Android Widget은 어떻게 개발할까? (0) | 2023.03.16 |
[Android] collectAsStateWithLifecycle를 이용하여 라이프사이클에 맞게 Flow 수집해보자!(feat. jetpack Compose) (1) | 2023.03.01 |