Android で入力されたパスワードの表示/非表示を切り替えてみた件（EditText）

# 概要

[Google Play ストア](https://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=5&cad=rja&uact=8&ved=0ahUKEwjn3-3UlM3WAhVFPrwKHVOxDNwQFgg6MAQ&url=https%3A%2F%2Fplay.google.com%2Fstore&usg=AOvVaw3cxGi8RcxeFexfEJZirjQS)のレビューに「メールアドレスとパスワードをちゃんと入力しているのに全然ログインできません！」といった苦情が多々寄せられるようになったため、[Slack](https://play.google.com/store/apps/details?id=com.Slack) アプリの様にパスワード入力フォームの目隠しを外せるようにする方針になりました。

# 調査してみた結果 :mag:

[Stack Overflow](https://stackoverflow.com/) の回答が引っかかりました。

- [Show the password with EditText](http://stackoverflow.com/questions/9307680/show-the-password-with-edittext)
- [How to switch between hide and view password](http://stackoverflow.com/questions/3685790/android-how-to-switch-between-hide-and-view-password)

一番評価が高かった回答を実際に試してみましたが、気になった点がいくつかありました。
![Screenshot_20160710-221332.png](https://qiita-image-store.s3.amazonaws.com/0/6881/0d9d0d12-0981-d8e1-6769-93347164beaf.png)

![Screenshot_20160710-221328.png](https://qiita-image-store.s3.amazonaws.com/0/6881/57ce0caf-316c-b5d4-59a9-0e460d63e27f.png)

:one: Android 4.0.4 の端末で文字入力直後にパスワードの表示/非表示を素早く切り替えると同じ文字が２文字連続で入力されてしまう :astonished: 
:two: パスワード表示/非表示状態の場合で文字列の長さが異る :disappointed_relieved: 
:three: ソフトキーボードの種類によっては表示/非表示を切り替えると英数字入力から日本語入力に変更されることがある :sob: 
:four: パスワードの表示/非表示を切り替えるとカーソルの位置が０文字目に移動してしまう :scream: 

# 更に調査してみた結果 :mag:

上記のような問題点が解消されているものがないか探してみたところ、Android でパスワード入力フォーム目隠しの表示/非表示を切り替えることができるライブラリを見つけました :arrow_right: [Show/Hide Password EditText](https://github.com/scottyab/showhidepasswordedittext)

# **追記**（2017.10.01）

[Design Support Library](https://developer.android.com/training/material/design-library.html) の [`24.2.0`](https://developer.android.com/topic/libraries/support-library/rev-archive.html#rev24-2-0) にて [TextInputLayout](https://developer.android.com/reference/android/support/design/widget/TextInputLayout.html) がパスワードの表示/非表示に対応したため、[Show/Hide Password EditText](https://github.com/scottyab/showhidepasswordedittext) の使用は 2016 年 8 月 18 日付けで非推奨になりました。

# **Deprecated になる以前**（2016.07.11 投稿時点）

## [Show/Hide Password EditText](https://github.com/scottyab/showhidepasswordedittext) を使ってみました
``` build.gradle
allprojects {
    repositories {
        maven {
            url "https://jitpack.io"
        }
    }
}
```

``` app/build.gradle
dependencies {
    compile 'com.github.scottyab:showhidepasswordedittext:0.8'
}
```

``` activity_password_input.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <com.scottyab.showhidepasswordedittext.ShowHidePasswordEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPassword" />
    <!-- パスワード入力フォーム -->
</android.support.percent.PercentRelativeLayout>
```

``` PasswordInputActivity.java
package jp.co.package.example;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;

/**
 * パスワード入力画面
 */
public class PasswordInputActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_password_input);
    }
}
```

![Screenshot_20160711-001203.png](https://qiita-image-store.s3.amazonaws.com/0/6881/2b48aca8-3fc3-345c-f267-dd5b29e686de.png)

![Screenshot_20160711-001154.png](https://qiita-image-store.s3.amazonaws.com/0/6881/99a06ee6-697e-d9dd-86b7-47f4f6ee86a5.png)

2016年7月10日時点のバージョン `0.8` では :eye: アイコンの Drawable が自動的に表示される仕組みになっているので、[CheckBox](https://developer.android.com/reference/android/widget/CheckBox.html) でパスワードの表示/非表示を切り替えできるようにしたい場合などは
 https://github.com/scottyab/showhidepasswordedittext/blob/master/library/src/main/java/com/scottyab/showhidepasswordedittext/ShowHidePasswordEditText.java から必要な部分を抜き出して独自実装する必要があります。

## [ライブラリ](https://github.com/scottyab/showhidepasswordedittext)からコードを抜き出して実装してみた

``` activity_password_input.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.AppCompatCheckBox
        android:id="@+id/checkbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true" />
    <!-- チェックボックス -->

    <jp.co.package.example.ShowHidePasswordEditText
        android:id="@+id/password_input_editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@id/checkbox"
        android:inputType="textPassword"
        android:singleLine="true" />
    <!-- 自前実装したパスワード入力フォーム -->
</android.support.percent.PercentRelativeLayout>
```

``` PasswordInputActivity.java
package jp.co.package.example;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

/**
 * パスワード入力画面
 */
public class PasswordInputActivity extends AppCompatActivity {

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

        final ShowHidePasswordEditText passwordEditText = (ShowHidePasswordEditText) findViewById(R.id.password_input_editText);
        findViewById(R.id.checkbox).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // チェックボックスがクリックされた時に呼び出されます
                passwordEditText.togglePasswordVisibility();
            }
        });
    }
}
```

![Screenshot_20160710-232936.png](https://qiita-image-store.s3.amazonaws.com/0/6881/5e15255d-699e-5c1d-b398-90461c7c4235.png)

![Screenshot_20160710-232931.png](https://qiita-image-store.s3.amazonaws.com/0/6881/0ae8dc5d-a2a8-8682-4b9c-0d8e6cb47d93.png)

## [ライブラリ](https://github.com/scottyab/showhidepasswordedittext)使用のメリット

:one: Android 4.0.4 端末で文字入力直後にパスワードの表示/非表示を素早く切り替えても直前に入力した文字が重複して入力されない :blush: 
:two: パスワード表示/非表示状態の場合で文字列の長さが同じ :smiley: （`android:inputType="textPassword"` を指定した場合）
:three: 表示/非表示を切り替えてもソフトキーボードが英数字入力のまま :smile: 
:four: 表示/非表示を切り替えてもカーソルの位置が保持される :laughing: 

~~という長所があるのでパスワードの表示/非表示を切り替えたい場合は [Show/Hide Password EditText](https://github.com/scottyab/showhidepasswordedittext) ライブラリの使用 or 参照がお勧めです。~~

# 結論

[TextInputLayout](https://developer.android.com/reference/android/support/design/widget/TextInputLayout.html) を使用するのが良いそうです :bow: