アンドロイドのTextInputLayoutの例
このチュートリアルでは、Android TextInputLayoutが提供する機能について詳しく見ていきます。Android TextInputLayoutは、マテリアルデザインサポートライブラリに付属しているデザインコンポーネントです。
アンドロイドのTextInputLayout
AndroidのTexInputLayoutはLinearLayoutを拡張しています。TextInputLayoutの主な使用目的は、EditText(またはその子孫)をラップし、浮動ヒントのアニメーションを有効にすることです。一般的なガイドラインとして、TextInputLayoutは通常のEditTextの代わりにTextInputEditTextをラップする必要があります。なぜなら、TextInputEditTextはEditTextのサブクラスであり、TextInputLayoutの子として使用するために設計されているからです。さらに、EditTextを使用すると警告が表示されます:”EditText added is not a TextInputEditText. Please switch to using that class instead.” TextInputLayoutは、浮動ヒントラベルを表示する以外にも多くの機能があります。
AndroidのTextInputLayoutの機能
今回のチュートリアルでカバーする主な特徴は以下の通りです:
-
- 浮動ヒントの有効化/無効化
-
- 浮動ヒントアニメーションの有効化/無効化
-
- エラーメッセージの表示
-
- 文字カウンターの表示
-
- 文字数制限を超えた場合にユーザーに警告する
-
- 浮動ヒント、エラーラベル、文字カウンターのテキストの外観をカスタマイズする
- パスワードの可視性の切り替え
これらの機能を一つずつ確認し、Android Studioプロジェクトに実装します。
アンドロイドのTextInputLayoutの例のプロジェクト構造。
これは単一のアクティビティのアプリケーションです。私たちはレイアウト、アクティビティ、styles.xmlおよびcolors.xmlファイルの中ですべての作業を行います。まず、以下に示すように、build.gradleファイルにデザインサポートライブラリの依存関係を追加してください。
compile 'com.android.support:design:25.3.1'
浮遊ヒントの有効化/無効化
ヒントの浮遊(Floating Hints)は、TextInputLayoutではデフォルトで有効になっています。無効にするには、以下の属性をタグ内に追加する必要があります : app:hintEnabled=”false”。以下は、activity_main.xml レイアウトから抜粋した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.scdev.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>
第3のEditTextフィールドはフローティングヒントが無効になっています。上記のコードの出力を見てみましょう。
浮遊ヒントアニメーションの有効化 / 無効化
前の機能と同様に、浮遊ヒントのアニメーションはデフォルトで有効になっています。無効にするには、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.scdev.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>
上記のコードの出力は以下に示す通りです。ただし、注目すべきは、2番目のEditTextフィールドがフォーカスされたときに浮き上がるヒントがアニメーションされないという点です。
ヒントのTextAppearanceをスタイリングする
ヒントのテキストカラーやテキストサイズをカスタマイズするには、以下の属性を使用します: 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レイアウトから取得したもので、ヒントテキストの表示設定がある場合とない場合のいずれかに対応した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.scdev.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>
上記のコードの出力は、以下に示されています。
文字数カウンター (Moji kazu kauntā)
文字カウンターは、数多くのアプリケーションで使用される機能です(Twitterの文字制限を覚えていますか?)。TextInputLayout内で使用する文字数の最大数を指定するには、app:counterEnabledをtrueに設定し、app:counterMaxLengthに最大文字数を指定します。文字カウンターはデフォルトで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.scdev.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>
上記のコードの出力は以下のとおりです。上記の出力をよく観察しましょう。
- The first EditText field changes its counter textColor, hint textColor and the indicator color when the character count is exceeded.
- The second EditText field does the same but also, it changes the counter custom textColor and custom textSize when the limit exceeds.
文字カウンターが制限を超えた場合に必要なスタイルを指定するために、次に見るcounterFlow属性を使用する必要があります。
文字数カウンターのオーバーフロー
上記で見たように、文字数が定義された制限を超える場合、カウンターテキストはcounterFlowで定義された属性を使用します。属性が存在しない場合は、上記の出力で見たようにデフォルトのものに固執します。次のparam 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.scdev.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クラスのインスタンスに対して、setError(String)メソッドを呼び出すことで、エラーテキストを表示する必要があります。
package com.scdev.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);
}
});
}
}
上記のコードでは、TextInputEditTextの各インスタンスに TextChangedListener(TextWatcherを実装)を追加します。現在の文字数がカウンターの最大制限を超える場合には、エラーラベルを表示します。エラーラベルをクリアするために、setError()内の値をnullに設定します。上記のコードの出力は次の通りです:注:テキストフィールドのインジケーターは、エラーラベルと同じ色を使用します。これはcounterOverflowによって設定された色を上書きするため、最優先の色となります。
パスワード表示切り替え
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.scdev.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>
上記のコードによって表示される出力は次の通りです:注意:app:passwordToggleDrawableを使用して、パスワードの可視性切り替えで独自のカスタムアイコンを使用することができます。これで、このチュートリアルは終了です。TextInputLayoutに存在する主要な機能をすべてカバーしました。以下のリンクからAndroid TextInputLayoutの例プロジェクトをダウンロードすることができます。上記のコードスニペットが含まれています。
Android TextInputLayout プロジェクトをダウンロードしてください。
参照:Android公式ドキュメント