TextInputLayout은 Android용 Material Components 라이브러리의 컴포넌트로, EditText를 래핑하고 고급 텍스트 입력 기능을 추가합니다. TextInputLayout의 주요 기능은 플로팅 레이블(floating label)로, 텍스트 입력 시 필드 위로 올라가 공간을 절약하고 가독성을 향상시킵니다. 또한 이 컴포넌트는 오류 메시지 표시, 필드 내 아이콘, 문자 카운터 및 다양한 스타일링 옵션을 지원합니다. Material Design Guidelines (2025)에 따르면, TextInputLayout은 Material Design 3 표준을 준수하는 Android 앱에서 텍스트 필드를 만드는 권장 방법입니다.
핵심 사항
TextInputLayout은 com.google.android.material.textfield 패키지의 ViewGroup으로, LinearLayout을 확장하고 내부에 EditText를 포함합니다. 이 컴포넌트는 버전 1.0.0부터 Android용 Material Components 라이브러리의 일부입니다. TextInputLayout의 주요 목적은 개발자의 최소한의 노력으로 Material Design 텍스트 필드의 즉시 사용 가능한 구현을 제공하는 것입니다.
표준 EditText와 달리, TextInputLayout은 내부 EditText의 android:hint 속성을 통해 설정되는 플로팅 레이블의 애니메이션을 관리합니다. 필드가 비어 있으면 레이블이 일반 힌트로 필드 내부에 표시됩니다. 사용자가 입력을 시작하면 레이블이 애니메이션과 함께 필드 상단으로 이동하고 크기가 작아집니다. Material Design Guidelines (2025)에 따르면, 이 애니메이션은 사용자가 데이터 입력 후에도 항상 필드 이름을 볼 수 있기 때문에 폼 인식을 향상시킵니다.
아키텍처적으로 TextInputLayout은 데코레이터 패턴을 구현합니다. EditText 이벤트를 가로채고 추가 요소(레이블, 오류, 아이콘, 카운터)의 표시를 관리하며 애니메이션을 조정합니다. 내부 EditText는 getEditText() 메서드를 통해 액세스할 수 있으며 inputType, maxLines 및 hint를 포함한 표준 속성으로 구성할 수 있습니다.
<!-- Basic TextInputLayout markup -->
@+id/tilEmail
android:layout_width="match_parent"
android:layout_height="wrap_content">
@+id/etEmail
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Email"
android:inputType="textEmailAddress" />
</com.google.android.material.textfield.TextInputLayout>
플로팅 레이블(floating label)은 TextInputLayout의 핵심 기능입니다. 필드가 비어 있으면 android:hint의 텍스트가 EditText 내부에 일반 플레이스홀더로 표시됩니다. 필드가 포커스를 받거나 텍스트가 입력되면 레이블이 TextInputLayout 상단으로 올라가고 글꼴 크기가 줄어들며 색상이 변경됩니다. 이 동작은 사용자가 입력을 시작한 후 힌트가 보이지 않게 되는 문제를 해결합니다.
플로팅 레이블 구성은 TextInputLayout 속성을 통해 수행됩니다. app:hintEnabled는 플로팅 레이블 활성화 여부를 결정하고(기본값 true), app:hintAnimationEnabled는 전환 애니메이션을 활성화/비활성화하며, app:expandedHintEnabled는 필드가 비어 있고 포커스되지 않은 경우에도 레이블 표시를 허용합니다. 다양한 상태에서의 레이블 색상은 colorPrimary 및 colorControlHighlight 스타일을 통해 관리됩니다.
Google Material Components Team (2025)에 따르면, 플로팅 레이블은 사용자가 입력을 시작한 후 필드 이름을 잊을 수 있는 많은 필드가 있는 폼에서 특히 유용합니다. 입력 시 사라지는 단순한 android:hint와 달리, 플로팅 레이블은 항상 표시되어 각 필드에 컨텍스트를 제공합니다.
| 속성 | 설명 | 기본값 |
|---|---|---|
| hintEnabled | 플로팅 레이블 활성화 또는 비활성화 | true |
| hintAnimationEnabled | 레이블 상승/하강 애니메이션 활성화 | true |
| expandedHintEnabled | 필드가 비어 있고 포커스가 없어도 레이블 표시 | false |
| hintTextAppearance | 플로팅 레이블 텍스트 스타일 | 앱 테마 |
TextInputLayout은 입력 필드와 시각적으로 통합된 내장 오류 표시 시스템을 제공합니다. setError 메서드를 통해 오류를 설정하면 컴포넌트가 필드를 강조 표시하고(선 또는 윤곽선 색상이 빨간색으로 변경됨) 필드 아래에 오류 텍스트를 표시합니다. 이렇게 하면 오류 메시지를 위한 별도의 TextView가 필요하지 않습니다.
오류 표시 관리는 setError(CharSequence) 및 setErrorEnabled(boolean) 메서드를 통해 수행됩니다. 텍스트와 함께 setError를 호출하면 오류가 즉시 표시되고, setError(null)을 호출하면 숨겨집니다. TextInputLayout은 app:errorIconDrawable 속성을 통한 맞춤 오류 아이콘과 app:errorTextColor를 통한 오류 색상 관리도 지원합니다.
Material Design Guidelines (2025)에 따르면, 오류 메시지는 구체적이고 유용해야 합니다. “잘못된 입력” 대신 “이메일에 @가 포함되어야 합니다”라고 작성합니다. 오류 표시는 입력 완료 후(포커스 손실 시 또는 폼 제출 후)에 이루어져야 하며 실시간이 아닙니다. 이는 폼 작성 시 사용자의 스트레스를 줄여줍니다.
// 프로그래밍 방식 오류 설정
textInputLayout.error = "Password min 8 chars"
// 오류 숨기기
textInputLayout.error = null
// 유효성 검사 오류 확인 및 설정
if (email.isNullOrBlank()) {
tilEmail.error = "Email is required"
} else {
tilEmail.error = null
}
TextInputLayout은 필드의 시작(start icon)과 끝(end icon) 모두에 아이콘 표시를 지원합니다. 아이콘은 비밀번호 표시 전환, 필드 지우기, 맞춤 작업 등 다양한 기능을 수행할 수 있습니다. 각 아이콘 유형은 별도의 속성으로 제어되며 app:startIconDrawable 또는 app:endIconDrawable 속성을 통해 맞춤 아이콘으로 교체할 수 있습니다.
끝 아이콘 모드는 app:endIconMode 속성을 통해 설정되며, 다음 값을 가질 수 있습니다: password_toggle — 비밀번호 표시 전환, clear_text — 필드 지우기, dropdown_menu — 드롭다운 목록 화살표, custom — 맞춤 아이콘. password_toggle의 경우 TextInputLayout이 textPassword와 textVisiblePassword 사이에서 inputType을 자동으로 전환하고 눈 아이콘도 애니메이션 처리합니다.
<!-- TextInputLayout with password toggle icon -->
@+id/tilPassword
android:layout_width="match_parent"
app:endIconMode="password_toggle"
app:passwordToggleTint="@color/primary">
@+id/etPassword
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
Android용 Material Components는 TextInputLayout에 두 가지 주요 스타일을 제공합니다: FilledBox(채워짐) 및 OutlinedBox(윤곽선). FilledBox 스타일은 색상이 채워진 배경과 필드 아래에 포커스 시 색상이 변경되는 선이 있습니다. OutlinedBox 스타일은 투명한 배경과 필드 전체를 둘러싼 윤곽선이 있어 더 명확한 경계를 만들고 많은 필드가 있는 폼에 더 적합합니다.
스타일 선택은 앱 디자인에 따라 다릅니다. FilledBox는 개별 필드에 덜 주의를 끌기 때문에 자주 사용하는 폼에 권장됩니다. OutlinedBox는 각 필드가 명확하게 표시되어야 하는 짧은 폼(로그인, 등록)에 선호됩니다. 스타일은 XML의 style 속성 또는 앱 테마를 통해 설정됩니다.
| 특성 | FilledBox | OutlinedBox |
|---|---|---|
| 배경 | 색상 채우기(일반적으로 회색) | 투명 |
| 경계 | 하단 선 | 필드 주위 윤곽선 |
| 포커스 | 선이 두꺼워지고 색상 변경 | 윤곽선 색상 변경 및 두꺼워짐 |
| 권장 | 빈번한 입력이 있는 폼 | 짧은 폼, 필드 강조 |
| 스타일 | Widget.MaterialComponents.TextInputLayout.FilledBox | Widget.MaterialComponents.TextInputLayout.OutlinedBox |
Material Design 3(M3)는 향상된 타이포그래피, 새로운 색상 토큰 및 Material You 동적 색상 지원과 함께 TextInputLayout에 대한 업데이트된 스타일을 도입했습니다. M3에서는 OutlinedBox가 기본 권장 스타일이 되었고, FilledBox는 새로운 사양에 맞게 패딩과 테두리 반경을 조정했습니다.
TextInputLayout을 사용한 등록 폼 구현의 전체 예제로, 이메일 및 비밀번호 유효성 검사, 오류 표시 및 비밀번호 표시 아이콘을 포함합니다. 등록 버튼을 누르면 모든 필드가 확인되고 해당 오류 메시지가 표시됩니다.
@+id/tilName
app:boxBackgroundMode="outlined">
@+id/etName
android:hint="Name" />
</...TextInputLayout>
@+id/tilRegEmail
app:boxBackgroundMode="outlined">
@+id/etRegEmail
android:hint="Email"
android:inputType="textEmailAddress" />
</...TextInputLayout>
@+id/tilRegPassword
app:boxBackgroundMode="outlined"
app:endIconMode="password_toggle">
@+id/etRegPassword
android:hint="Password"
android:inputType="textPassword" />
</...TextInputLayout>
private fun validateForm(): Boolean {
var isValid = true
if (etName.text.isNullOrBlank()) {
tilName.error = "Enter your name"
isValid = false
} else {
tilName.error = null
}
val email = etRegEmail.text.toString()
if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
tilRegEmail.error = "Invalid email format"
isValid = false
} else {
tilRegEmail.error = null
}
val password = etRegPassword.text.toString()
if (password.length < 8) {
tilRegPassword.error = "Password min 8 chars"
isValid = false
} else {
tilRegPassword.error = null
}
return isValid
}
자주 묻는 질문
TextInputLayout은 com.google.android.material 라이브러리 버전 1.0.0부터 사용할 수 있습니다. Material Design 3 기능을 사용하려면 버전 1.6.0 이상을 사용하세요. 모듈 build.gradle에 implementation “com.google.android.material:material:1.12.0”을 포함하세요.
포커스 상태의 플로팅 레이블 색상은 app:hintTextColor 속성 또는 colorPrimary를 사용한 테마를 통해 제어됩니다. 다양한 상태(포커스, 오류, 비활성화)에는 res/color/의 선택기 또는 Material Components 라이브러리의 boxStrokeColor, errorTextColor 속성을 사용하세요.
app:counterEnabled=“true” 속성을 설정하고 app:counterMaxLength=“100”으로 최대 문자 수를 지정하세요. TextInputLayout이 자동으로 필드 하단에 카운터를 표시합니다(예: “25/100”). 카운터 색상은 app:counterTextColor로, 제한 초과 시 app:counterOverflowTextColor로 구성할 수 있습니다.
FilledBox — 배경이 색상으로 채워짐, 하단 선 강조. 시각적 공간을 덜 차지합니다. OutlinedBox — 필드 주위 윤곽선이 있는 투명 배경, 더 선명한 경계. FilledBox는 빈번한 입력 필드에, OutlinedBox는 각 필드의 명확성이 중요한 짧은 폼에 권장됩니다.
네, app:hintEnabled=“false” 속성을 설정하여 플로팅 레이블을 비활성화하세요. 이 경우 TextInputLayout은 EditText의 일반 래퍼로 작동하며 오류, 아이콘 및 문자 카운터 기능은 유지하지만 레이블 애니메이션은 없습니다. 힌트가 필요하지 않거나 맞춤 레이블을 사용하는 필드에 유용합니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.