[Android] Compose TextField 커스텀

2025. 6. 12. 14:49·Android

만들고 싶었던 것

  • MaterialDesign이 적용되지 않은 `TextField`
  • width가 입력되어있는 텍스트 길이 만큼 wrapCotent할 것
  • Placeholder 표시

결과는 아래와 같다.  
붉은 글씨 부분이 placeholder를 표시하고있는 `TextField`임


구현 과정

1. MaterialDesign이 없는 TextField

일반적인 `TextField` 컴포저블을 사용하면 MaterialDesign을 피할 수 없기 때문에,  
아무 디자인도 적용되지 않은 `BasicTextField`를 사용해야 한다.

BasicTextField(
    value = text,
     onValueChange = { onTextChange(it) },
    ...
)


호출하면 기본 width를 가지는 텅빈 `TextField`가 표시된다.  
(width를 표시하기 위해 회색으로 background를 칠했습니다)

 

2. width를 wrapContent로 만들기

`TextField`는 기본적으로 최소 width를 가지고 있는데,  
이것을 제거하려면 `Modifier.width(IntrinsicSize.Min)`을 적용해야 한다.

BasicTextField(
    value = text,
     onValueChange = { onTextChange(it) },
    modifier = Modifier.width(IntrinsicSize.Min)
)


그러면 텍스트가 없기 때문에 width가 완전히 쪼그라든다.  
텍스트를 입력하면 맞춰서 길이가 늘어난다.


3. Placeholder 표시

`BasicTextField`는 placeholder를 설정하는 파라미터가 직접적으로 없다.  
`TextField` 컴포저블의 구현코드를 보면 `DecorationBox`에 `placeholder`를 넘겨서 표시하고 있다.


그러면 `DecorationBox`를 사용해서 표시하면 되겠다 했는데..  
`TextFieldDefaults`의 `DecorationBox`라서 그런지 저걸 사용하게 되면 MaterialDesign이 적용되어버린다.

나 뭐 어떡하라고. 커스텀 하라는거야 말라는거야

구글링 결과 그냥 때려박아버리기로 했음

Box {
    var text by remember {
        mutableStateOf("")
    }

    val hintVisible by remember {
        derivedStateOf { text.isEmpty() }
    }

    if (hintVisible) {
        // placeholder 용 Text
        Text(
            text = "어떤 이유"
            modifier = Modifier.alpha(0.5f)
        )
    }

    BasicTextField(
        value = text,
        onValueChange = { text = it },
        modifier = Modifier.width(IntrinsicSize.Min)
    )
}


별거 없고 그냥 입력한 텍스트가 empty면 placeholder로 사용할 `Text`를 표시하고,  
텍스트가 입력되면 `Text`를 표시하지 않는다.

 


잘되는 것 같아 보인다.

 

문제

처음엔 빈칸이니까 `BasicTextField`의 width가 쪼그라든 상태라 `Box` 영역의 맨 앞부분을 터치해야만 키보드가 뜬다..

그렇다고 `BasicTextField`의 width를 `Modifier.matchParentSize`로 지정해버리면 텍스트를 입력했을 때 텍스트가 보이지 않게 된다.  
`Modifier.fillMaxWidth`를 사용하면 당연히 `BasicTextField`의 width가 화면을 꽉채우게 된다.

뭐 어떡하라고.

 

해결

`IntrinsicSize.Min/Max`라는게 content를 그리기 위한 최소/최대의 Size를 받아와서  
child를 measure 할 때 제약사항을 적용하는 것이다.

그래서 `BasicTextField`를 감싸는 상위 컴포저블인 `Box`의 width를 `IntrinsicSize.Max`로 지정하고  
(-> `Box`의 width가 `BasicTextField`보다 긴 placeholder용 `Text`의 width 만큼이 됨)

`BasicTextField`의 width는 `Modifier.fillMaxWidth`로 지정해준다.  
(-> `Box`의 width 제약사항 때문에 딱 `Box`의 width만큼만 fill 하게됨)

Box(
    modifier = Modifier.width(IntrinsicSize.Max) // 여기
) {
    var text by remember {
        mutableStateOf("")
    }

    val hintVisible by remember {
        derivedStateOf { text.isEmpty() }
    }

    if (hintVisible) {
        // placeholder용 Text
        Text(
            text = "어떤 이유",
            modifier = Modifier.alpha(0.5f)
        )
    }

    BasicTextField(
        value = text,
        onValueChange = { text = it },
        modifier = Modifier
            .fillMaxWidth() // 여기
            .background(Color.LightGray.copy(alpha = 0.4f))    // width 확인용
    )
}

 


`BasicTextField`가 빈칸인데도 placeholder의 width만큼 늘어나있는 것이 잘 보인다.  
이제 어딜 눌러도 키보드가 열린다.

 

끝

이번 기회를 통해 `IntrinsicSize`에 대해서 정확히 알게 되었다^^

'Android' 카테고리의 다른 글

[Android] 멀티모듈에서 gradle의 BuildType 공통화  (2) 2025.06.12
[Android] java.lang.ClassCastException  (0) 2025.06.12
[Android] LazyColumn안에 LazyVerticalGrid 넣기(nested scroll)  (0) 2025.06.12
[Android] Retrofit2 Multipart사용하기 (Java)  (0) 2025.06.12
[Android] RecyclerView와 ListAdapter (Java)  (1) 2025.06.12
'Android' 카테고리의 다른 글
  • [Android] 멀티모듈에서 gradle의 BuildType 공통화
  • [Android] java.lang.ClassCastException
  • [Android] LazyColumn안에 LazyVerticalGrid 넣기(nested scroll)
  • [Android] Retrofit2 Multipart사용하기 (Java)
th.k
th.k
dev-thk 님의 블로그 입니다.
  • th.k
    dev-thk 님의 블로그
    th.k
  • 전체
    오늘
    어제
    • 분류 전체보기 (9)
      • Android (8)
      • Kotlin (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • Github
  • 공지사항

    • Contact
  • 인기 글

  • 태그

    retrofit2
    Flow
    ListAdapter
    Compose
    ktor
    RecyclerView
    gradle
    Java
    Kotlin
    Android
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
th.k
[Android] Compose TextField 커스텀
상단으로

티스토리툴바