在密碼輸入框中添加顯示明文功能

歡迎Follow我的GitHub, 關(guān)注我的簡書. 其余參考Android目錄.

Password

本文的合集已經(jīng)編著成書兽泣,高級(jí)Android開發(fā)強(qiáng)化實(shí)戰(zhàn)涩咖,歡迎各位讀友的建議和指導(dǎo)。在京東即可購買:https://item.jd.com/12385680.html

Android

在使用App的時(shí)候, 首次都需要輸入密碼. 有些人為了安全性, 密碼較長, 偶爾會(huì)輸入錯(cuò)誤; 有些人忘記了密碼, 需要多次嘗試, 但又不知道是輸入錯(cuò)誤, 還是密碼錯(cuò)誤, 這些都會(huì)影響用戶體驗(yàn).

這一點(diǎn), 移動(dòng)端設(shè)計(jì)師們早有準(zhǔn)備, 因?yàn)槭謾C(jī)的私密性較強(qiáng), 在輸入密碼時(shí), 可以提示用戶顯式輸入, 增強(qiáng)準(zhǔn)確性, 提升體驗(yàn). 這些當(dāng)然是有成本的, 需要額外編寫功能. 因此, 我來講一下, 如何編寫密碼明文顯示的功能, 減少大家的學(xué)習(xí)成本.

本文源碼的GitHub下載地址

要點(diǎn)
(1) 重寫EditText, 添加提示密碼顯示和隱藏的圖片.
(2) 判斷點(diǎn)擊位置, 切換EditText的密碼顯示狀態(tài).
(3) 在屏幕旋轉(zhuǎn)或配置改變時(shí), 保留圖片的狀態(tài)信息.

實(shí)現(xiàn)只有一個(gè)類和兩個(gè)圖片資源, 大家可以自由定制.


1. 布局樣式

兩種密碼的顯示樣式, 一種是常規(guī)顯示, 一種是TextInputLayout顯示.

    <LinearLayout
        android:id="@+id/main_ll_container_1"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:gravity="center">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="密碼:"
            android:textSize="20sp"/>

        <me.chunyu.spike.wcl_password_input_demo.PasswordEditText
            android:id="@+id/main_pet_password"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:hint="請輸入密碼"/>

    </LinearLayout>

    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/main_ll_container_1">

        <me.chunyu.spike.wcl_password_input_demo.PasswordEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:hint="請輸入密碼"/>

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

效果

顯示

2. 提示圖標(biāo)

初始化資源和布局, 獲取密碼圖片的資源, 監(jiān)聽EditText, 有文字時(shí)顯示圖標(biāo), 沒有文字時(shí)隱藏圖標(biāo).

    // 初始化布局
    public void initFields(AttributeSet attrs, int defStyleAttr) {
        if (attrs != null) {
            // 獲取屬性信息
            TypedArray styles = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.PasswordEditText, defStyleAttr, 0);
            try {
                // 根據(jù)參數(shù), 設(shè)置Icon
                mShowPwdIcon = styles.getResourceId(R.styleable.PasswordEditText_pet_iconShow, mShowPwdIcon);
                mHidePwdIcon = styles.getResourceId(R.styleable.PasswordEditText_pet_iconHide, mHidePwdIcon);
            } finally {
                styles.recycle();
            }
        }

        // 密碼狀態(tài)
        setInputType(EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);

        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) {
                if (s.length() > 0) {
                    // 有文字時(shí)顯示指示器
                    showPasswordVisibilityIndicator(true);
                } else {
                    mIsShowPwdIcon = false;
                    restorePasswordIconVisibility(mIsShowPwdIcon);
                    showPasswordVisibilityIndicator(false); // 隱藏指示器
                }
            }

            @Override public void afterTextChanged(Editable s) {

            }
        });
    }

setInputType設(shè)置密碼狀態(tài), TYPE_TEXT_VARIATION_PASSWORD密文狀態(tài).
通過pet_iconShow屬性, 可以選擇自定義密碼提示圖片.


3. 監(jiān)聽事件

點(diǎn)擊圖片, 切換顯示或隱藏密碼, 獲取點(diǎn)擊位置, 和圖片位置進(jìn)行比較, 判斷事件.

    @Override public boolean onTouchEvent(MotionEvent event) {
        if (mDrawableSide == null) {
            return super.onTouchEvent(event);
        }
        final Rect bounds = mDrawableSide.getBounds();
        final int x = (int) event.getRawX(); // 點(diǎn)擊的位置

        int iconX = (int) getTopRightCorner().x;

        // Icon的位置
        int leftIcon = iconX - bounds.width();

        Log.e(TAG, "x: " + x + ", leftIcon: " + leftIcon);

        // 大于Icon的位置, 才能觸發(fā)點(diǎn)擊
        if (x >= leftIcon) {
            togglePasswordIconVisibility(); // 變換狀態(tài)
            event.setAction(MotionEvent.ACTION_CANCEL);
            return false;
        }
        return super.onTouchEvent(event);
    }

切換明文或密文的密碼

    // 設(shè)置密碼指示器的狀態(tài)
    private void restorePasswordIconVisibility(boolean isShowPwd) {
        if (isShowPwd) {
            // 可視密碼輸入
            setInputType(EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
        } else {
            // 非可視密碼狀態(tài)
            setInputType(EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
        }

        // 移動(dòng)光標(biāo)
        setSelection(getText().length());
    }

4. 保存狀態(tài)

重寫SavedState, 在旋轉(zhuǎn)屏幕時(shí), 保存和恢復(fù)顯示圖片信息.

    // 存儲(chǔ)密碼狀態(tài), 顯示Icon的位置
    protected static class PwdSavedState extends BaseSavedState {

        private final boolean mShowingIcon;

        private PwdSavedState(Parcelable superState, boolean showingIcon) {
            super(superState);
            mShowingIcon = showingIcon;
        }

        private PwdSavedState(Parcel in) {
            super(in);
            mShowingIcon = in.readByte() != 0;
        }

        public boolean isShowingIcon() {
            return mShowingIcon;
        }

        @Override
        public void writeToParcel(Parcel destination, int flags) {
            super.writeToParcel(destination, flags);
            destination.writeByte((byte) (mShowingIcon ? 1 : 0));
        }

        public static final Parcelable.Creator<PwdSavedState> CREATOR = new Creator<PwdSavedState>() {
            public PwdSavedState createFromParcel(Parcel in) {
                return new PwdSavedState(in);
            }

            public PwdSavedState[] newArray(int size) {
                return new PwdSavedState[size];
            }
        };
    }

動(dòng)畫效果

動(dòng)畫

現(xiàn)在可以把類復(fù)制到應(yīng)用中, 更換圖片資源, 替換顯示密碼框, 給用戶更好的移動(dòng)端體驗(yàn). 永遠(yuǎn)追求極致, 追求不凡.

OK, that's all! Enjoy it!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末瓣铣,一起剝皮案震驚了整個(gè)濱河市术辐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌克婶,老刑警劉巖筒严,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丹泉,死亡現(xiàn)場離奇詭異情萤,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)摹恨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門筋岛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人晒哄,你說我怎么就攤上這事睁宰》净瘢” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵柒傻,是天一觀的道長孝赫。 經(jīng)常有香客問我,道長红符,這世上最難降的妖魔是什么青柄? 我笑而不...
    開封第一講書人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮预侯,結(jié)果婚禮上致开,老公的妹妹穿的比我還像新娘。我一直安慰自己萎馅,他們只是感情好双戳,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著糜芳,像睡著了一般飒货。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上峭竣,一...
    開封第一講書人閱讀 49,079評(píng)論 1 285
  • 那天膏斤,我揣著相機(jī)與錄音,去河邊找鬼邪驮。 笑死莫辨,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的毅访。 我是一名探鬼主播沮榜,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼喻粹!你這毒婦竟也來了蟆融?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤守呜,失蹤者是張志新(化名)和其女友劉穎型酥,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體查乒,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡弥喉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了玛迄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片由境。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出虏杰,到底是詐尸還是另有隱情讥蟆,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布纺阔,位于F島的核電站瘸彤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏笛钝。R本人自食惡果不足惜钧栖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望婆翔。 院中可真熱鬧拯杠,春花似錦、人聲如沸啃奴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽最蕾。三九已至依溯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瘟则,已是汗流浹背黎炉。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留醋拧,地道東北人慷嗜。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像丹壕,于是被迫代替她去往敵國和親庆械。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,515評(píng)論 25 707
  • 內(nèi)容抽屜菜單ListViewWebViewSwitchButton按鈕點(diǎn)贊按鈕進(jìn)度條TabLayout圖標(biāo)下拉刷新...
    皇小弟閱讀 46,708評(píng)論 22 664
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程菌赖,因...
    小菜c閱讀 6,358評(píng)論 0 17
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫缭乘、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,029評(píng)論 4 62
  • 清理自己就是對(duì)自己曾經(jīng)有過的借口進(jìn)行圍剿琉用, 突破自己就是拒絕接口堕绩; 重新開始。 無論在處理緊急時(shí)間打破瓶頸等工作環(huán)...
    zhoujia閱讀 519評(píng)論 0 0