Android實(shí)現(xiàn)驗(yàn)證碼、密碼輸入框

最近在做項(xiàng)目的時(shí)候,有這樣一個(gè)需求,要實(shí)現(xiàn)取件碼的輸入,效果圖如下:
要實(shí)現(xiàn)效果

看到這個(gè)圖,立馬想到,這個(gè)類似于支付寶、微信的密碼輸入框。

實(shí)現(xiàn)方法總結(jié):
一、直接寫四個(gè)EditText,然后對(duì)其設(shè)置maxLength為1。
  <EditText
      android:id="@+id/et_inputPickupNum1"
      android:layout_width="40dp"
      android:layout_height="40dp"
      android:inputType="number"
      android:gravity="center"
      android:maxLength="1"
      android:background="#0000ff"/>
在代碼中,對(duì)其設(shè)置監(jiān)聽(tīng)事件,事件主要功能如下:

1)當(dāng)有輸入后,立馬使其失去焦點(diǎn),同時(shí)讓下一個(gè)EditText獲取焦點(diǎn)。
2)當(dāng)刪除的時(shí)候,使其使其失去焦點(diǎn),同時(shí)讓前一個(gè)獲取焦點(diǎn)。

        etPickupNum2.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 (!TextUtils.isEmpty(s.toString().trim())){
                    etPickupNum2.clearFocus();
                    etPickupNum2.setFocusable(false);
                    etPickupNum3.setFocusable(true);
                    etPickupNum3.setFocusableInTouchMode(true);
                    etPickupNum3.requestFocus();
                }else{
                    etPickupNum2.clearFocus();
                    etPickupNum1.setFocusable(true);
                    etPickupNum1.setFocusableInTouchMode(true);
                    etPickupNum1.requestFocus();
                }
            }

            @Override
            public void afterTextChanged(Editable s) {
            }
        });
不過(guò),這種實(shí)現(xiàn)方式代碼量大,可擴(kuò)展性差。這種實(shí)現(xiàn)方式,還存在一個(gè)問(wèn)題,就是刪除一個(gè)后,光標(biāo)跳到前一個(gè)去了,繼續(xù)輸入還得點(diǎn)一下EditText。
二、在同一個(gè)布局容器中添加四個(gè)TextView,用于顯示輸入后的文字。同時(shí)在這個(gè)布局容器上邊添加一個(gè)背景透明的、隱藏了光標(biāo)、字體也是透明的EditText。在代碼中,對(duì)EditText設(shè)置輸入監(jiān)聽(tīng)事件。

1)xml文件中:

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="40dp">


            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/tv_inputPickupNum1"
                    android:layout_width="40dp"
                    android:layout_height="40dp"
                    android:textColor="#ffffff"
                    android:background="#0000ff"/>

                <View
                    android:layout_weight="1"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"/>

                  .......

            </LinearLayout>

            <EditText
                android:id="@+id/et_inputPickupNum"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:maxLength="4"
                android:background="@android:color/transparent"
                android:textColor="@android:color/transparent"
                <!--cursorVisible設(shè)置為false,表示隱藏光標(biāo)-->
                android:cursorVisible="false"/>
        </RelativeLayout>

2)代碼中:

        etnum.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) {
                //numList是一個(gè)存放四個(gè)TextView的集合
                for (TextView tvNum:numList){
                   tvNum.setText("");
                }
                String str = s.toString().trim();
                if (!TextUtils.isEmpty(str)){
                    for(int i = 0;i < str.length();i++){
                        numList.get(i).setText(str.substring(i,i+1));
                    }
                }
            }

            @Override
            public void afterTextChanged(Editable s) {
            }
        });
這種和第一種比較,就是不用考慮焦點(diǎn)的得失。
三、自定義View。實(shí)現(xiàn)思路是:

1) 定義內(nèi)容背景顏色、間距、間距顏色、字體顏色等屬性。
2)在xml中設(shè)置這些屬性值。
3)寫一個(gè)類繼承EditText,獲取上邊屬性值,并且實(shí)現(xiàn)輸入事件監(jiān)聽(tīng)。
4)做全局配置:讓該EditText獲取焦點(diǎn),再設(shè)置最大長(zhǎng)度。設(shè)置字體顏色為透明,隱藏光標(biāo)。

    private void initView() {
        setFocusable(true);
        setFocusableInTouchMode(true);
        this.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)});
        this.setTextColor(Color.TRANSPARENT);
        this.setGravity(Gravity.CENTER_VERTICAL);
        if(mPaint == null){
            mPaint = new Paint();
        }
        mPaint.setTextSize(textSize);
        mPaint.setColor(spacingColor);
        if (mBound == null){
            mBound = new Rect();
        }
    }

5)設(shè)置背景,實(shí)現(xiàn)四個(gè)顯示框,以及中間間距。

private void drawBackground(Canvas canvas) {
         //contentWidth為顯示框?qū)挾?,spacingWidth為間距寬度,maxLength為最大長(zhǎng)度
        contentWidth = (getWidth() - spacingWidth*(maxLength-1))/maxLength;
        for (int i = 0;i < maxLength;i++){
            //contentColor為文本框背景顏色
            mPaint.setColor(contentColor);
            Rect rect = new Rect(i*(spacingWidth + contentWidth),0,i*(spacingWidth + contentWidth) + contentWidth,getHeight());
            canvas.drawRect(rect,mPaint);

            if (i != maxLength -1){
                //spacingColor為間距的背景顏色
                mPaint.setColor(spacingColor);
                Rect spacingRect = new Rect(i*(spacingWidth + contentWidth) + contentWidth,0,(i+1)*(spacingWidth + contentWidth),getHeight());
                canvas.drawRect(spacingRect,mPaint);
            }
        }
    }

6)繪制文字。

        //content用于記錄當(dāng)前輸入字符串
        mPaint.getTextBounds(content,0,content.length(),mBound);
        mPaint.setColor(textColor);
        for (int i = 0;i < content.length();i++){
            canvas.drawText(content.substring(i,i+1),i*(spacingWidth + contentWidth),getHeight()/2 + mBound.height()/2,mPaint);
        }

這種方式和第二種相比,缺點(diǎn)是需要計(jì)算文本顯示區(qū)域,間距顯示區(qū)域。優(yōu)點(diǎn)是擴(kuò)展性好一點(diǎn)。
最后編輯于
?著作權(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)容

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