Android 自定義密碼輸入框

效果

自定義密碼輸入框又跛,項目的一個界面需求流酬,我把這個自定義的輸入框提取出來作為這次內(nèi)容的題目蓉驹。
輸入前:


image.png

輸入后:


image.png

輸入1個字符就紅一個圈圈,很簡單的效果搂橙。

思路

1.自定義EditText歉提。
2.背景為一個外圓環(huán)加內(nèi)實心圓。
3.edittext的長度變化時候重新繪制背景或者紅色環(huán)位置区转。

關(guān)鍵代碼

代碼其實也很簡單苔巨,順手拿資源的請到文末。

1.畫背景

  /**
     * 繪制背景外圓
     */
    private void drawOutRing(Canvas canvas) {
        mPaint.setColor(mBgColor);
        // 設(shè)置畫筆為空心
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(mBgSize);
        RectF rectF = new RectF(mBgSize, mBgSize, getWidth() - mBgSize, getHeight() - mBgSize);
        // 畫圓
        for (int i = 0; i < mPasswordNumber; i++) {
            int cx = i * mDivisionLineSize + i * mPasswordItemWidth + mPasswordItemWidth / 2 + mBgSize;
            canvas.drawCircle(cx, getHeight() / 2, mOutRadius, mPaint);
        }

    }

2.畫實心內(nèi)圓背景

   /**
     * 繪制背景內(nèi)圓
     */
    private void drawInRing(Canvas canvas) {
        mPaint.setColor(mDivisionLineColor);
        // 設(shè)置畫筆為實心
        mPaint.setStyle(Paint.Style.FILL);
        // 畫圈圈
        for (int i = 0; i < mPasswordNumber; i++) {
            int cx = i * mDivisionLineSize + i * mPasswordItemWidth + mPasswordItemWidth / 2 + mBgSize;
            canvas.drawCircle(cx, getHeight() / 2, mPasswordRadius, mPaint);
        }
    }
}

3.繪制輸入密碼的變化動作

/**
     * 繪制隱藏的密碼
     */
    private void drawHidePassword(Canvas canvas) {
        int passwordLength = getText().length();
        if (passwordLength > 6) passwordLength = 6;
        mPaint.setColor(mPasswordColor);
        // 畫實心內(nèi)圓
        mPaint.setStyle(Paint.Style.FILL);
        for (int i = 0; i < passwordLength; i++) {
            int cx = i * mDivisionLineSize + i * mPasswordItemWidth + mPasswordItemWidth / 2 + mBgSize;
            canvas.drawCircle(cx, getHeight() / 2, mPasswordRadius, mPaint);
        }
        //外圓顏色
        mPaint.setColor(mPasswordColor);
        // 設(shè)置畫筆為空心
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(mBgSize);
        RectF rectF = new RectF(mBgSize, mBgSize, getWidth() - mBgSize, getHeight() - mBgSize);
        // 畫空心外圓
        for (int i = 0; i < passwordLength; i++) {
            int cx = i * mDivisionLineSize + i * mPasswordItemWidth + mPasswordItemWidth / 2 + mBgSize;
            canvas.drawCircle(cx, getHeight() / 2, mOutRadius, mPaint);
        }

    }

4.重寫onDraw

   int passwordWidth = getWidth() - (mPasswordNumber - 1) * mDivisionLineSize;
        mPasswordItemWidth = passwordWidth / mPasswordNumber;
        // 繪制背景外圓
        drawOutRing(canvas);
        // 繪制背景內(nèi)圓
        drawInRing(canvas);
        // 繪制密碼
        drawHidePassword(canvas);

5.xml引用

 <com***.PasswordView
        android:id="@+id/password"
        android:layout_width="240dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="10dp"
        android:background="@null">
    </com***.PasswordView>

6.還可以設(shè)置些屬性
在sytle中設(shè)置废离,通過xml中的app:xxx引用侄泽。

 <com.*.PasswordView
        android:id="@+id/password"
        android:layout_width="240dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="10dp"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        app:bgColor="#ffffff"
        android:background="@null">
    </com.*.PasswordView>

完整代碼

一些樣式,我設(shè)置了蜻韭,結(jié)果直接沒用上

    <declare-styleable name="PasswordView">
        <!-- 密碼的個數(shù) -->
        <attr name="passwordNumber" format="integer"/>
        <!-- 密碼圓點的半徑 -->
        <attr name="passwordRadius" format="dimension"/>
        <!-- 密碼圓點的顏色 -->
        <attr name="passwordColor" format="color"/>
        <!-- 外圈顏色 -->
        <attr name="outRingColor" format="color"/>
        <!-- 外圓線條大小 -->
        <attr name="outRingLineSize" format="color"/>
        <!-- 背景邊框的顏色 -->
        <attr name="bgColor" format="color"/>
        <!-- 背景邊框的大小 -->
        <attr name="bgSize" format="dimension"/>
        <!-- 背景邊框的圓角大小 -->
        <attr name="bgCorner" format="dimension"/>
    </declare-styleable>

自定義Edittext

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
/**
 *自定義密碼輸入框
 */

public class PasswordView extends EditText {
    // 畫筆
    private Paint mPaint;
    // 一個密碼所占的寬度
    private int mPasswordItemWidth;
    // 密碼的個數(shù)默認為6位數(shù)
    private int mPasswordNumber = 6;
    // 背景圓顏色
    private int mBgColor = Color.parseColor("#d1d2d6");
    // 背景大小
    private int mBgSize = 1;
    // 背景邊框圓角大小
    private int mBgCorner = 0;
    // 外圓的顏色
    private int outRingLineColor = mBgColor;
    // 外圓線條的大小
    private int outRingLineSize = 1;
    // 密碼輸入的顏色
    private int mPasswordColor = Color.parseColor("#cb3435");
     // 密碼圓點的半徑大小
    private int mPasswordRadius = 6;
    // 外圓半徑大小
    private int mOutRadius = 25;
    public PasswordView(Context context) {
        this(context, null);
    }

    public PasswordView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initPaint();
        initAttributeSet(context, attrs);
        // 設(shè)置輸入模式是密碼
        setInputType(EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
        // 不顯示光標
        setCursorVisible(false);
    }

    /**
     * 初始化屬性
     */
    private void initAttributeSet(Context context, AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PasswordView);
        // 獲取大小
        outRingLineSize = (int) array.getDimension(R.styleable.PasswordView_outRingLineSize, dip2px(outRingLineSize));
        mPasswordRadius = (int) array.getDimension(R.styleable.PasswordView_passwordRadius, dip2px(mPasswordRadius));
        mBgSize = (int) array.getDimension(R.styleable.PasswordView_bgSize, dip2px(mBgSize));
        mBgCorner = (int) array.getDimension(R.styleable.PasswordView_bgCorner, 0);
        // 獲取顏色
        mBgColor = array.getColor(R.styleable.PasswordView_bgColor, mBgColor);
        outRingLineColor = array.getColor(R.styleable.PasswordView_outRingColor, outRingLineColor);
        mPasswordColor = array.getColor(R.styleable.PasswordView_passwordColor, mPasswordColor);
        array.recycle();
    }

    /**
     * 初始化畫筆
     */
    private void initPaint() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
    }

    /**
     * dip 轉(zhuǎn) px
     */
    private int dip2px(int dip) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dip, getResources().getDisplayMetrics());
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int passwordWidth = getWidth() - (mPasswordNumber - 1) * outRingLineSize;
        mPasswordItemWidth = passwordWidth / mPasswordNumber;
        // 繪制背景外圓
        drawOutRing(canvas);
        // 繪制背景內(nèi)圓
        drawInRing(canvas);
        // 繪制密碼
        drawHidePassword(canvas);
    }

    @Override
    public void setText(CharSequence text, BufferType type) {
        super.setText(text, type);
    }
    /**
     * 繪制背景外圓
     */
    private void drawOutRing(Canvas canvas) {
        mPaint.setColor(mBgColor);
        // 設(shè)置畫筆為空心
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(mBgSize);
        RectF rectF = new RectF(mBgSize, mBgSize, getWidth() - mBgSize, getHeight() - mBgSize);
        // 畫圓
        for (int i = 0; i < mPasswordNumber; i++) {
            int cx = i * outRingLineSize + i * mPasswordItemWidth + mPasswordItemWidth / 2 + mBgSize;
            canvas.drawCircle(cx, getHeight() / 2, mOutRadius, mPaint);
        }

    }

    /**
     * 繪制隱藏的密碼
     */
    private void drawHidePassword(Canvas canvas) {
        int passwordLength = getText().length();
        if (passwordLength > 6) passwordLength = 6;
        mPaint.setColor(mPasswordColor);
        // 設(shè)置畫筆為實心
        mPaint.setStyle(Paint.Style.FILL);
        for (int i = 0; i < passwordLength; i++) {
            int cx = i * outRingLineSize + i * mPasswordItemWidth + mPasswordItemWidth / 2 + mBgSize;
            canvas.drawCircle(cx, getHeight() / 2, mPasswordRadius, mPaint);
        }
        //外圓
        mPaint.setColor(mPasswordColor);
        // 設(shè)置畫筆為空心
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(mBgSize);
        RectF rectF = new RectF(mBgSize, mBgSize, getWidth() - mBgSize, getHeight() - mBgSize);
        // 如果沒有設(shè)置圓角悼尾,就畫矩形
        for (int i = 0; i < passwordLength; i++) {
            int cx = i * outRingLineSize + i * mPasswordItemWidth + mPasswordItemWidth / 2 + mBgSize;
            canvas.drawCircle(cx, getHeight() / 2, mOutRadius, mPaint);
        }

    }

    /**
     * 繪制背景內(nèi)圓
     */
    private void drawInRing(Canvas canvas) {
        mPaint.setColor(outRingLineColor);
        // 設(shè)置畫筆為實心
        mPaint.setStyle(Paint.Style.FILL);
        // 畫圈圈
        for (int i = 0; i < mPasswordNumber; i++) {
            int cx = i * outRingLineSize + i * mPasswordItemWidth + mPasswordItemWidth / 2 + mBgSize;
            canvas.drawCircle(cx, getHeight() / 2, mPasswordRadius, mPaint);
        }
    }
}

結(jié)束

有事請留言。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末湘捎,一起剝皮案震驚了整個濱河市诀豁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌窥妇,老刑警劉巖舷胜,帶你破解...
    沈念sama閱讀 212,686評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡烹骨,警方通過查閱死者的電腦和手機翻伺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,668評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吨岭,“玉大人,你說我怎么就攤上這事辣辫。” “怎么了急灭?”我有些...
    開封第一講書人閱讀 158,160評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長谷遂。 經(jīng)常有香客問我葬馋,道長肾扰,這世上最難降的妖魔是什么畴嘶? 我笑而不...
    開封第一講書人閱讀 56,736評論 1 284
  • 正文 為了忘掉前任集晚,我火速辦了婚禮窗悯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘偷拔。我一直安慰自己蟀瞧,他們只是感情好条摸,可當我...
    茶點故事閱讀 65,847評論 6 386
  • 文/花漫 我一把揭開白布铸屉。 她就那樣靜靜地躺著,像睡著了一般彻坛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上昌屉,一...
    開封第一講書人閱讀 50,043評論 1 291
  • 那天,我揣著相機與錄音间驮,去河邊找鬼。 笑死扛施,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的疙渣。 我是一名探鬼主播,決...
    沈念sama閱讀 39,129評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼泼菌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了哗伯?” 一聲冷哼從身側(cè)響起刷钢,我...
    開封第一講書人閱讀 37,872評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎内地,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體阱缓,經(jīng)...
    沈念sama閱讀 44,318評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,645評論 2 327
  • 正文 我和宋清朗相戀三年敞嗡,在試婚紗的時候發(fā)現(xiàn)自己被綠了航背。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,777評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡玖媚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出今魔,到底是詐尸還是另有隱情,我是刑警寧澤错森,帶...
    沈念sama閱讀 34,470評論 4 333
  • 正文 年R本政府宣布吟宦,位于F島的核電站,受9級特大地震影響涩维,放射性物質(zhì)發(fā)生泄漏殃姓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,126評論 3 317
  • 文/蒙蒙 一锋叨、第九天 我趴在偏房一處隱蔽的房頂上張望宛篇。 院中可真熱鬧,春花似錦叫倍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,861評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至须妻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間荒吏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,095評論 1 267
  • 我被黑心中介騙來泰國打工瞧挤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留儡湾,地道東北人。 一個月前我還...
    沈念sama閱讀 46,589評論 2 362
  • 正文 我出身青樓徐钠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子宋税,可洞房花燭夜當晚...
    茶點故事閱讀 43,687評論 2 351

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,858評論 25 707
  • 先看最終效果圖可在布局文件中配置各種屬性杰赛,如密碼框個數(shù),密碼框圓角半徑,顏色瘦赫,中間圓半徑和大小蛤迎,padding值也...
    shada閱讀 1,623評論 7 3
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件替裆、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,066評論 4 62
  • ¥開啟¥ 【iAPP實現(xiàn)進入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,375評論 0 17
  • 只有自己感覺好,才可以讓身邊人更好 做自己的女王逗威,遇見更好的自己 當我們呱呱墜地的時候,我們享受著來自身...
    夢雅書廊閱讀 369評論 0 0