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

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

Password

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

Android

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

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

本文源碼的GitHub下載地址

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

實(shí)現(xiàn)只有一個(gè)類(lèi)和兩個(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="請(qǐng)輸入密碼"/>

    </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="請(qǐng)輸入密碼"/>

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

效果

顯示

2. 提示圖標(biāo)

初始化資源和布局, 獲取密碼圖片的資源, 監(jiān)聽(tīng)EditText, 有文字時(shí)顯示圖標(biāo), 沒(méi)有文字時(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).
通過(guò)pet_iconShow屬性, 可以選擇自定義密碼提示圖片.


3. 監(jiān)聽(tīng)事件

點(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)

重寫(xiě)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)畫(huà)效果

動(dòng)畫(huà)

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

OK, that's all! Enjoy it!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容