웹사이트 검색

Android TextInputLayout 예제


이 튜토리얼에서는 Android TextInputLayout이 제공하는 기능을 자세히 살펴보겠습니다. Android TextInputLayout은 머티리얼 디자인 지원 라이브러리와 함께 제공되는 디자인 구성 요소입니다.

Android TextInputLayout

Android TexInputLayout은 LinearLayout을 확장합니다. TextInputLayout의 주요 용도는 EditText(또는 그 자손)에 대한 래퍼 역할을 하고 플로팅 힌트 애니메이션을 활성화하는 것입니다. 경험 법칙: TextInputLayout은 일반 EditText 대신 TextInputEditText를 래핑해야 합니다. 이유? TextInputEditText는 EditText의 하위 클래스이며 TextInputLayout의 자식으로 사용하도록 설계되었습니다. 또한 대신 EditText를 사용하면 다음과 같은 경고가 표시됩니다. 추가된 EditText는 TextInputEditText가 아닙니다. 대신 해당 클래스를 사용하도록 전환하십시오. TextInputLayout은 부동 힌트 레이블을 표시하는 것보다 훨씬 더 많은 기능을 제공합니다.

Android TextInputLayout 기능

이 튜토리얼에서 다룰 기능 중 일부는 다음과 같습니다.

  1. 플로팅 힌트 활성화/비활성화
  2. 플로팅 힌트 애니메이션 활성화/비활성화
  3. 오류 메시지 표시
  4. 문자 카운터 표시
  5. 문자 수가 한도를 초과할 때 사용자에게 경고
  6. 플로팅 힌트, 오류 레이블, 문자 카운터에 대한 텍스트 모양 사용자 지정
  7. 비밀번호 표시 토글

이러한 각 기능을 살펴보고 Android 스튜디오 프로젝트에서 구현할 것입니다.

Android TextInputLayout 예제 프로젝트 구조

compile 'com.android.support:design:25.3.1'

플로팅 힌트 활성화/비활성화

플로팅 힌트는 TextInputLayout에서 기본적으로 활성화됩니다. 비활성화하려면 태그 안에 app:hintEnabled=\false\ 속성을 추가해야 합니다. 아래 xml 코드는 activity_main.xml 레이아웃에서 가져온 것으로 3개의 EditText 필드가 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">


        <android.support.design.widget.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            android:hint="TextInputEditText" />


        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="@dimen/activity_horizontal_margin">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Floating Hint Enabled Default" />

        </android.support.design.widget.TextInputLayout>


        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:hintEnabled="false">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Floating Hint Disabled" />

        </android.support.design.widget.TextInputLayout>

</LinearLayout>
</ScrollView>

플로팅 힌트 애니메이션 활성화/비활성화

이전 기능과 마찬가지로 플로팅 힌트 애니메이션은 기본적으로 활성화되어 있습니다. 비활성화하려면 TextInputLayout 태그 안에 다음 특성을 추가해야 합니다. app:hintAnimationEnabled=\false\ 아래 xml 코드는 activity_main.xml 레이아웃에서 가져온 것이며 각 경우에 대한 EditText 필드가 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="@dimen/activity_horizontal_margin">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Floating Hint Enabled Default" />

        </android.support.design.widget.TextInputLayout>


        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:hintAnimationEnabled="false">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Hint Animation Disabled" />

        </android.support.design.widget.TextInputLayout>

</LinearLayout>
</ScrollView>

힌트 TextAppearance 스타일 지정

힌트에 사용자 지정 textColortextSize를 사용하려면 다음 속성이 사용됩니다. app:hintTextAppearance=\@style/HintText\ HintText 스타일 아래와 같이 styles.xml 내부에 작성됩니다.

<style name="HintText" parent="TextAppearance.Design.Hint">
        <item name="android:textSize">16sp</item>
        <item name="android:textColor">@color/colorPrimary</item>
    </style>

아래 xml 코드는 activity_main.xml 레이아웃에서 가져온 것이며 두 가지 경우(hintTextAppearance 포함/제외)에 대한 EditText 필드가 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="@dimen/activity_horizontal_margin">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Floating Hint Enabled" />

        </android.support.design.widget.TextInputLayout>


        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:hintTextAppearance="@style/HintText">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Custom Hint TextAppearance" />

        </android.support.design.widget.TextInputLayout>

</LinearLayout>
</ScrollView>

문자 카운터

문자 카운터는 꽤 많은 응용 프로그램에서 사용되는 기능입니다. (Twitter 글자 수 제한을 기억하시나요?). app:counterEnabled를 true로 설정하고 app:counterMaxLength를 TextInputLayout에서 원하는 최대 문자 수로 설정합니다. 문자 카운터는 기본적으로 EditText(오른쪽 하단) 아래에 표시되며 이 튜토리얼을 작성하는 동안에는 아직 위치를 변경할 방법이 없습니다. 카운터 스타일 지정은 힌트 텍스트 스타일 지정과 유사합니다. app:counterTextAppearance는 이번에 사용된 속성입니다. 프로젝트의 styles.xml 파일 내에 다음 스타일을 추가했습니다.

<style name="CounterText" parent="TextAppearance.Design.Counter">
        <item name="android:textSize">16sp</item>
        <item name="android:textColor">@color/my_pink</item>
    </style>

아래 xml 코드는 activity_main.xml 레이아웃에서 가져온 것으로 기본 문자 카운터와 사용자 지정 카운터가 있는 EditText 필드가 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:counterEnabled="true"
            app:counterMaxLength="5"
            app:hintTextAppearance="@style/HintText">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Character Counter Limit 10" />

        </android.support.design.widget.TextInputLayout>


        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:counterEnabled="true"
            app:counterMaxLength="5"
            app:counterTextAppearance="@style/CounterText"
            app:hintTextAppearance="@style/HintText">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Character Counter Custom TextAppearance" />

        </android.support.design.widget.TextInputLayout>

</LinearLayout>
</ScrollView>

  • 첫 번째 EditText 필드는 문자 수를 초과할 때 카운터 textColor, 힌트 textColor 및 표시기 색상을 변경합니다.
  • 두 번째 EditText 필드는 동일한 작업을 수행하지만 제한을 초과하면 카운터 사용자 지정 textColor 및 사용자 지정 textSize를 변경합니다.

문자 카운터가 한계를 초과할 때 필요한 스타일을 지정하려면 다음에 보게 될 counterFlow 속성을 사용해야 합니다.

문자 카운터 오버플로

문자 수가 정의된 제한을 초과할 때 위에서 본 것처럼 카운터 텍스트는 counterFlow에 정의된 속성을 사용합니다. 속성이 없으면 위 출력에서 본 것처럼 기본 속성을 고수합니다. 다음 매개변수 app:counterOverflowTextAppearance를 사용해야 합니다. CounterOverflow의 스타일은 styles.xml 안에 있습니다.

 <style name="CounterOverFlow" parent="TextAppearance.Design.Counter.Overflow">
        <item name="android:textSize">16sp</item>
        <item name="android:textColor">@color/my_orange</item>
    </style>

아래 코드 스니펫을 이전 activity_main.xml 레이아웃에 추가합니다.

<android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:counterEnabled="true"
            app:counterMaxLength="5"
            app:counterOverflowTextAppearance="@style/CounterOverFlow"
            app:counterTextAppearance="@style/CounterText"
            app:hintTextAppearance="@style/HintText">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="CounterOverflow CustomTextAppearance" />

        </android.support.design.widget.TextInputLayout>

오류 레이블

app:errorEnabled를 true로 설정하면 EditText 필드 아래 조건에 따라 오류 텍스트를 표시할 수 있습니다. 오류 텍스트의 스타일을 지정하려면 app:errorTextAppearance 속성을 사용하고 styles.xml 파일에 다음 코드를 추가합니다.

<style name="ErrorText" parent="TextAppearance.Design.Error">
        <item name="android:textSize">16sp</item>
        <item name="android:textColor">@color/my_black</item>
    </style>

아래 xml 코드는 activity_main.xml 레이아웃에서 가져온 것으로 기본 오류 레이블과 사용자 정의 레이블에 대한 EditText 필드가 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <android.support.design.widget.TextInputLayout
            android:id="@+id/errorInputLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:counterEnabled="true"
            app:counterMaxLength="5"
            app:counterOverflowTextAppearance="@style/CounterOverFlow"
            app:counterTextAppearance="@style/CounterText"
            app:errorEnabled="true"
            app:hintTextAppearance="@style/HintText">

            <android.support.design.widget.TextInputEditText
                android:id="@+id/errorEditText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Default Error Label" />

        </android.support.design.widget.TextInputLayout>


        <android.support.design.widget.TextInputLayout
            android:id="@+id/customErrorInputLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:counterEnabled="true"
            app:counterMaxLength="5"
            app:counterOverflowTextAppearance="@style/CounterOverFlow"
            app:counterTextAppearance="@style/CounterText"
            app:errorEnabled="true"
            app:errorTextAppearance="@style/ErrorText"
            app:hintTextAppearance="@style/HintText">

            <android.support.design.widget.TextInputEditText
                android:id="@+id/customErrorEditText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Custom Error Label" />

        </android.support.design.widget.TextInputLayout>

</LinearLayout>
</ScrollView>

오류 텍스트를 표시하려면 아래와 같이 MainActivity.java 클래스의 TextInputLayout 인스턴스에서 setError(String) 메서드를 호출해야 합니다.

package com.journaldev.featuresoftextinputlayout;

import android.support.design.widget.TextInputEditText;
import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;

public class MainActivity extends AppCompatActivity {


    TextInputLayout errorInputLayout, customErrorInputLayout;
    TextInputEditText errorEditText, customErrorEditText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        errorEditText = (TextInputEditText) findViewById(R.id.errorEditText);
        errorInputLayout = (TextInputLayout) findViewById(R.id.errorInputLayout);

        customErrorEditText = (TextInputEditText) findViewById(R.id.customErrorEditText);
        customErrorInputLayout = (TextInputLayout) findViewById(R.id.customErrorInputLayout);

        errorEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {

                if (s.length() > errorInputLayout.getCounterMaxLength())
                    errorInputLayout.setError("Max character length is " + errorInputLayout.getCounterMaxLength());
                else
                    errorInputLayout.setError(null);

            }
        });

        customErrorEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {

                if (s.length() > customErrorInputLayout.getCounterMaxLength())
                    customErrorInputLayout.setError("Max character length is " + customErrorInputLayout.getCounterMaxLength());
                else
                    customErrorInputLayout.setError(null);

            }
        });


    }
}

비밀번호 가시성 전환

app:passwordToggleEnabled를 true로 설정하면 암호를 표시하거나 숨길 수 있습니다. 아이콘 색상을 변경하려면 app:passwordToggleTint를 사용하세요. 아래 xml 코드는 activity_main.xml 레이아웃에서 가져온 것으로 비밀번호 가시성 토글(기본 아이콘 및 색조 포함)에 대한 EditText 필드가 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context="com.journaldev.featuresoftextinputlayout.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:counterEnabled="true"
            app:counterMaxLength="5"
            app:counterOverflowTextAppearance="@style/CounterOverFlow"
            app:counterTextAppearance="@style/CounterText"
            app:hintTextAppearance="@style/HintText"
            app:passwordToggleEnabled="true">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Password Visibility Toggle"
                android:inputType="textPassword" />

        </android.support.design.widget.TextInputLayout>


        <android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/activity_horizontal_margin"
            app:counterEnabled="true"
            app:counterMaxLength="5"
            app:counterOverflowTextAppearance="@style/CounterOverFlow"
            app:counterTextAppearance="@style/CounterText"
            app:hintTextAppearance="@style/HintText"
            app:passwordToggleEnabled="true"
            app:passwordToggleTint="@color/my_orange">

            <android.support.design.widget.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Password Visibility Toggle Tint"
                android:inputType="textPassword" />

        </android.support.design.widget.TextInputLayout>
</LinearLayout>
</ScrollView>

Android TextInputLayout 프로젝트 다운로드

참조: Android 공식 문서