WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

Floating Labels for EditTextを実装してみた

今回のエンジニアブログを担当する佐藤です。

前回FAB(Floating Action Button)に引き続き、TextInputLayoutをつかったFloating Labels for EditTextを実装したいと思います。

【Floating Labels for EditText】
Floating Labels for EditTextは、TextInputLayoutを使用したMaterial DesignのTextEditです。
TextInputLayoutはDesign Support Libraryに追加された機能です。

TextInputLayoutを使用すると、入力フォーム選択時にラベルがフォームの上へ移動するアニメーションをするようになります。
Screenshot_2015-10-09-19-53-13

実装はとても簡単でした。
今回もDesign Support Library使用するので、build.gradleに追記していきます。

build.gradle

dependencies {  
    compile 'com.android.support:design:22.2.0'  
}  

レイアウトは以下のようになっています。
activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:paddingLeft="@dimen/activity_horizontal_margin"  
    android:paddingRight="@dimen/activity_horizontal_margin"  
    android:paddingTop="@dimen/activity_vertical_margin"  
    android:paddingBottom="@dimen/activity_vertical_margin"  
    android:orientation="vertical"  
    tools:context=".MainActivity">  
  
    <android.support.design.widget.TextInputLayout  
        android:id="@+id/input_name"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content">  
  
        <EditText  
            android:id="@+id/name"  
            android:layout_width="match_parent"  
            android:layout_height="wrap_content"  
            android:singleLine="true"  
            android:hint="@string/name" />  
    </android.support.design.widget.TextInputLayout>  
  
    <android.support.design.widget.TextInputLayout  
        android:id="@+id/input_password"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content">  
        <EditText  
            android:id="@+id/password"  
            android:layout_width="match_parent"  
            android:layout_height="wrap_content"  
            android:inputType="textPassword"  
            android:hint="@string/password" />  
  
    </android.support.design.widget.TextInputLayout>  
</LinearLayout>  
  

string.xml

<?xml version="1.0" encoding="utf-8"?>  
<resources>  
    <string name="app_name">FloationgLabelTextEdit</string>  
    <string name="name">名前</string>  
    <string name="password">パスワード</string>  
</resources>  

android:hintで設定した文字が入力フォームに表示されています。

また、TextInputLayoutはsetError()でエラーメッセージを表示することができます。
MainActivity.java

public class MainActivity extends Activity{  
    TextInputLayout inputLayoutName;  
    TextInputLayout inputLayoutPassword;  
    EditText textName;  
    EditText textPassword;  
    Button btnOk;  
    HashMap<String, Boolean> errorCheck;  
  
    // パスワードの最小文字数  
    final int PASS_MIN = 6;  
    // パスワードの最大文字数  
    final int PASS_MAX = 12;  
  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        errorCheck = new HashMap<String, Boolean>();  
        errorCheck.put("name", false);  
        errorCheck.put("password", false);  
  
        inputLayoutName = (TextInputLayout) findViewById(R.id.input_name);  
        inputLayoutPassword = (TextInputLayout) findViewById(R.id.input_password);  
  
        textName = (EditText) findViewById(R.id.name);  
        textPassword = (EditText) findViewById(R.id.password);  
  
        // 入力中のチェック  
        textName.addTextChangedListener(new EditTextWatcher(textName));  
        textPassword.addTextChangedListener(new EditTextWatcher(textPassword));  
  
        btnOk = (Button) findViewById(R.id.btn_ok);  
        btnOk.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View view) {  
                // 名前の入力とパスワードの入力に不備がなければToastを表示  
                if(checkNameInput() || checkPassInput()) {  
                    Toast.makeText(view.getContext(), view.getContext().getText(R.string.input_success), Toast.LENGTH_SHORT).show();  
                }else{  
                    updateButton();  
                }  
            }  
        });  
    }  
  
    /**  
     * 「名前」の入力チェック  
     */  
    private boolean checkNameInput(){  
        // 空白ならエラー表示  
        if(textName.getText().toString().trim().isEmpty()){  
            inputLayoutName.setError(getString(R.string.error_name_empty));  
            return false;  
        }  
  
        inputLayoutName.setErrorEnabled(false);  
        return true;  
    }  
  
    /**  
     * 「パスワード」の入力チェック  
     */  
    private  boolean checkPassInput(){  
        String password = textPassword.getText().toString().trim();  
        // 空白ならエラー表示  
        if(password.length() == 0){  
            inputLayoutPassword.setError(getString(R.string.error_pass_empty));  
            return false;  
        }  
  
        // 最小文字数以下ならエラー表示  
        if(password.length() < PASS_MIN){  
            inputLayoutPassword.setError(getString(R.string.error_pass_min, PASS_MIN));  
            return false;  
        }  
          
        // 最大文字数を超えていたらエラー  
        if(password.length() > PASS_MAX){  
            inputLayoutPassword.setError(getString(R.string.error_pass_max, PASS_MAX));  
            return false;  
        }  
  
        inputLayoutPassword.setErrorEnabled(false);  
        return true;  
    }  
  
    /**  
     * OKボタンの状態を更新  
     */  
    private void updateButton(){  
        // 入力内容に不備があれば押せないようにする  
        if(!errorCheck.get("name") || !errorCheck.get("password")){  
            btnOk.setEnabled(false);  
        }else{  
            btnOk.setEnabled(true);  
        }  
    }  
  
    /**  
     * 入力フォームの状態を取得する  
     */  
    private class EditTextWatcher implements TextWatcher {  
        View v;  
  
        public EditTextWatcher(EditText editText) {  
            v = editText;  
        }  
  
        @Override  
        public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {  
  
        }  
  
        @Override  
        public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {  
  
        }  
  
        @Override  
        public void afterTextChanged(Editable editable) {  
            // 文字を入力時に入力内容をチェックしエラーの表示やボタンの状態を更新する  
            switch (v.getId()) {  
                case R.id.name:  
                    errorCheck.put("name", checkNameInput());  
                    break;  
                case R.id.password:  
                    errorCheck.put("password", checkPassInput());  
                    break;  
            }  
            updateButton();  
        }  
    }  
}  

実機で確認するとこうなりました!

◆起動時
Screenshot_2015-10-12-19-34-27

◆空白でOK押下時
Screenshot_2015-10-12-19-34-36

◆パスワード入力中エラーチェック
Screenshot_2015-10-12-19-34-59

◆エラーなし
Screenshot_2015-10-12-19-35-05

動きが細かいですが、このような細かい動きでもMaterialDesignらしいアプリケーションになるので積極的に実装していきたいです!