Jetpack Compose TextFieldState 사용하기

2024. 10. 24. 00:28·Jetpack Compose
목차
  1. 시작하며
  2. TextFieldState
  3. - public properties
  4. - function
  5. BasicTextField
  6. Reference

시작하며

Compose의 TextField로는 String과 TextFieldValue를 사용하는 두 개의 버전이 존재한다. TextFieldValue는 selection을 포함하고 있는 클래스로 String을 사용하는 기본 TextField에 커서 위치를 조절할 수 있는 기능이 추가된 버전이다. 

하지만 일반 TextField는 커스텀이 어려운 편이라 커스텀하기 용이한 BasicTextField를 사용하게 되는데 BasicTextField에는 기존 두 가지 버전 이외에도 TextFieldState를 사용하는 버전이 추가되어 총 세 가지 버전이 존재한다.

 

이 글에서는 그중에서 TextFieldState이 사용되는 BasicTextField와 TextFieldState에 대해 알아본다. 

 

TextFieldState

초기화할 때 initialText와 initialSelection을 입력할 수 있으며, saver가 포함된 rememberTextFieldState()를 호출해 초기화하면 된다.(뷰모델에서는 TextFieldState() 사용)

// Composable 함수에서
val textFieldState = rememberTextFieldState()
// ViewModel에서
val textFieldState = TextFieldState()

 

- public properties

• text : TextFieldState는 특이하게 CharSequence를 사용한다. CharSequence는 String의 상위 인터페이스로 toString() 등의 함수로 String으로 변환해 사용할 수 있다.

 

• selection : TextFieldValue에 있던 selection과 동일한 TextRange 타입으로 기존 TextFieldValue와는 edit 함수를 사용해 프로그래밍식으로 변경할 수 있다는 차이가 있다.

 

• composition : 마찬가지로 TextFieldValue에 있던 것과 동일하며 ime에서 관리하는 구성 범위로 예를 들어 한자나 일본어, 이모티콘을 입력할 때 ime가 일부를 잠시동안 유지해 사용자가 선택할 수 있게 한다.

 

• undoState : TextFieldState에서 새롭게 추가된 기능으로 되돌리기 기능을 지원한다. undo, redo, canUndo, canRedo, cleanHistory 등의 함수를 호출해 사용하면 된다.

 

- function

TextFieldState은 수신 객체 지정 람다를 사용하는 edit 함수와 TextFieldState의 확장 함수를 사용해 편집할 수 있다.

먼저 edit은 TextFieldBuffer의 확장 함수를 람다로 받아와서 실행하는 함수로 사용할 수 있는 사용할 수 있는 대표적인 함수로는 insert, delete, replace, append 등이 있다. 

// 확장 함수
fun TextFieldBuffer.insert(index: Int, text: String) {
replace(index, index, text)
}
fun TextFieldBuffer.delete(start: Int, end: Int) {
replace(start, end, "")
}
// 멤버 함수
override fun append(char: Char): Appendable = apply {
onTextWillChange(length, length, 1)
buffer.replace(buffer.length, buffer.length, char.toString())
}

내부 코드를 확인해 보면 append는 맨 끝에 공백을 한 개 추가해 주는 함수로 TextFieldBuffer 클래스의 멤버 함수인 반면 insert와 delete는 TextFieldBuffer의 확장 함수로 약간의 차이가 있지만 동일하게 edit 내부에서 사용할 수 있다. 이때 대부분의 함수가 replace를 사용하는 함수인 것을 알 수 있는데 replace에 대해 더 자세히 알아보면

internal fun replace(
start: Int,
end: Int,
text: CharSequence,
textStart: Int = 0,
textEnd: Int = text.length
) {
require(start <= end) { "Expected start=$start <= end=$end" }
require(textStart <= textEnd) { "Expected textStart=$textStart <= textEnd=$textEnd" }
onTextWillChange(start, end, textEnd - textStart)
buffer.replace(start, end, text, textStart, textEnd)
}
fun replace(start: Int, end: Int, text: CharSequence) {
replace(start, end, text, 0, text.length)
}

시작과 끝, 그리고 text를 입력받아 내부에서 length를 사용해 처리하는 함수인 것을 알 수 있다. 이때 두 가지 replace 모두 TextFieldBuffer의 멤버 함수이다.

그 외에 두 개의 TextFieldBuffer 확장 함수가 더 있는데 placeCursorEnd(커서를 마지막에 배치), selectAll(모두 선택)이 있다.

 

다음으로 TextFieldState의 확장 함수는 자주 사용하는 기능을 사용하기 편리하게 확장 함수로 구현해 둔 것으로 세 가지 함수가 존재한다. 필자는 setText라는 함수를 추가로 만들어서 커서와 선택 관련 기능이 필요하지 않을 때 호출해 사용하고 있다. 

// 새롭게 텍스트를 설정 후 커서를 마지막에 위치
fun TextFieldState.setTextAndPlaceCursorAtEnd(text: String) {
edit {
replace(0, length, text)
placeCursorAtEnd()
}
}
// 새롭게 텍스트를 설정 후 모두 선택
fun TextFieldState.setTextAndSelectAll(text: String) {
edit {
replace(0, length, text)
selectAll()
}
}
// 텍스트 모두 삭제
fun TextFieldState.clearText() {
edit {
delete(0, length)
placeCursorAtEnd()
}
}
// 커스텀 함수, 텍스트 설정
fun TextFieldState.setText(text: String) {
edit {
replace(0, length, text)
}
}

 

BasicTextField

androidx.compose.foundation:foundation 1.7.0 버전 중요 변경사항에 아래와 같이 설명되어 있다.

이제 TextFieldState를 사용하는 BasicTextField가 안정화되었으므로 모든 호출 사이트에서 BasicTextField(value, onValueChange)에서 BasicTextField(TextFieldState)로 이전을 시작하는 것이 좋습니다.

그렇다면 왜 TextFieldState를 사용하는 BasicTextField를 사용하는 것이 좋을까?

아래는 각각 String/TextFieldValue/TextFieldState를 사용하는 BasicTextField에 간단한 단어를 입력하고 있는 영상이다.

- 안드로이드 스튜디오의 layout inspector를 사용해 재구성 횟수를 확인할 수 있으며 왼쪽 영상의 파랗게 표시되는 게 재구성(recomposition)되고 있다는 뜻이고 오른쪽 트리의 숫자 중 왼쪽이 실제 재구성 횟수, 오른쪽이 건너뛰어진 횟수이다. 

 

- Strng/TextFieldValue를 사용하는 BasicTextField(value, onValueChange)는 value가 텍스트를 직접 관리하기 때문에 텍스트를 입력해 값이 변경될 때마다 TextField 전체가 재구성된다.

 

- TextFieldState를 사용하는 BasicTextField는 TextFieldState가 텍스트를 관리하기 때문에 텍스트를 입력해 값이 변경되어도 재구성되지 않는다. 

 

이처럼 불필요한 재구성을 줄여 성능 최적화에 도움이 되며 앞에서 설명한 것처럼 커서, 텍스트 선택, undo 기능 캡슐화 및 보존/복원 용이 등 여러 장점이 많기 때문에 BasicTextField(TextFieldState)를 사용하는 것을 추천한다.

 

해당 BasicTextField를 사용하는 방법은 아래 글에서 이어서 설명한다.

https://developuzzle.tistory.com/entry/Jetpack-Compose-BasicTextFieldTextFieldState-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

 

[Jetpack Compose] BasicTextField(TextFieldState) 사용하기

시작하며BasiceTextField에는 value/onValueChange를 사용하는 버전과 TextFieldState를 사용하는 버전이 존재한다. 이 글에서는 TextFieldState를 사용하는 BasicTextField에 대해 자세히 알아본다. TextFieldState에 대한

developuzzle.tistory.com

 

Reference

https://developer.android.com/reference/kotlin/androidx/compose/foundation/text/input/TextFieldState

 

TextFieldState  |  Android Developers

androidx.appsearch.builtintypes.properties

developer.android.com

https://developer.android.com/jetpack/androidx/releases/compose-foundation?hl=ko#1.7.0

 

Compose 기초  |  Jetpack  |  Android Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Compose 기초 즉시 사용 가능한 구성요소를 사용해 Jetpack

developer.android.com

https://developer.android.com/develop/ui/compose/tooling/layout-inspector?hl=ko

 

Layout Inspector  |  Jetpack Compose  |  Android Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. Layout Inspector 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Layout Inspector를 사용하면 에뮬레이터나 실

developer.android.com

https://medium.com/androiddevelopers/effective-state-management-for-textfield-in-compose-d6e5b070fbe5

 

Effective state management for TextField in Compose

TL;DR — The Compose roadmap reflects the work that the team is doing on multiple fronts, in this case Text Editing Improvements and…

medium.com

  1. 시작하며
  2. TextFieldState
  3. - public properties
  4. - function
  5. BasicTextField
  6. Reference
'Jetpack Compose' 카테고리의 다른 글
  • 버전 충돌로 인한 오류, 안정화 버전으로 해결하는 법
  • Jetpack Compose BasicTextField(TextFieldState) 사용하기
  • Jetpack Compose로 해시태그(Hashtag) 입력 기능 만들기
  • Jetpack Compose Ripple(물결) 효과 제거하기
브애애앳
브애애앳
  • 브애애앳
    디벨로퍼즐
    브애애앳
  • 전체
    오늘
    어제
    • 분류 전체보기 (24) N
      • Android App (3) N
      • Android Studio (2)
      • Figma (0)
      • Jetpack Compose (15)
      • Kotlin (3)
      • Tistory (1)
  • 인기 글

  • hELLO· Designed By정상우.v4.10.0
브애애앳
Jetpack Compose TextFieldState 사용하기

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.