Android自定義類似支付寶密碼輸入的控件

前言:感覺自己記憶力不是很好,很多寫過的東西容易忘記,所以還是寫個博客記錄一下,菜鳥一枚,望各位師傅指點。

嘿喂狗,來看我們要實現的效果(如果你說:”開發之前當然看不到效果,看個diao啊“。我只能說:會YY嗎【PS:老猿可能覺得此程序比較簡單,勿噴哈:)】)

這裏寫圖片描述

接下來,講講如何實現,自定義控件一般分爲三種:
1、繼承已有的控件來實現自定義控件,如本例就需要繼承EditText
2、繼承一個佈局文件實現自定義控件
3、繼承view類來實現自定義控件

我們實現的效果爲第一種情況,繼承現有的控件,本例我們需繼承EditText

實現步驟(此步驟爲我的習慣而已)
1、根據需求,確定需要自定義的屬性(初學者也可不自定義屬性,先寫死,然後再考慮自定義屬性)
2、在res/values/attrs.xml中定義屬性
3、新建類,繼承EditText,然後–啪啪啪–碼功能

首先,思考有哪些東西需要自定義,本例可以自定義的有:邊框顏色,邊框寬度,圓角弧度,間隔線顏色,間隔線寬度,字體大小,字體顏色,數字個數等。

好,我們先看在attrs中如何自定義屬性(name爲屬性名,format爲此屬性的值類型)

<resources>
    <declare-styleable name="VerifyEditView">
        <attr name="VerifyBorderWidth" format="dimension" />
        <attr name="VerifyBorderColor" format="color" />
        <attr name="VerifyBorderRadius" format="dimension" />
        <attr name="VerifyCodeTextSize" format="dimension" />
        <attr name="VerifyCodeTextColor" format="color" />
        <attr name="VerifyCodeLength" format="integer" />
    </declare-styleable>
</resources>

然後,新建類VerifyEditView

public class VerifyEditView extends EditText {
    private int mBorderColor;
    private int mBorderWidth;
    private int mBorderRadius;

    private int mCodeLength;
    private int mCodeColor;
    private int mCodeSize;

    private Paint mPaint;
    private int mWidth;
    private int mHeight;
    private RectF mRectF;

    private String mTextContent;
    private int mTextLength;

    //當不需要使用xml聲明或者不需要使用inflate動態加載時候,實現此構造函數即可 
    public VerifyEditView(Context context) {
        this(context,null);
    }
    //在xml創建但是沒有指定style的時候被調用
    public VerifyEditView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }
    //有指定style的時候被調用(注:雖然我將代碼寫在這地方,但是我並沒有指定style,事實上,程序會使用第二個構造函數,只是將第三個參數傳0而已)
    public VerifyEditView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //獲取我們在attrs定義的自定義屬性
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.VerifyEditView,defStyleAttr,0);
        mBorderColor = a.getColor(R.styleable.VerifyEditView_VerifyBorderColor, Color.BLACK);//第二個參數爲默認值,當我們在使用此控件但是沒有定義此屬性值的時候,會使用此處設置的默認值
        mBorderWidth = a.getDimensionPixelSize(R.styleable.VerifyEditView_VerifyBorderWidth, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics()));
        mBorderRadius = a.getDimensionPixelSize(R.styleable.VerifyEditView_VerifyBorderRadius, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,5,getResources().getDisplayMetrics()));

        mCodeColor = a.getColor(R.styleable.VerifyEditView_VerifyCodeTextColor,Color.BLACK);
        mCodeLength = a.getInt(R.styleable.VerifyEditView_VerifyCodeLength,6);
        mCodeSize = a.getDimensionPixelSize(R.styleable.VerifyEditView_VerifyCodeTextSize, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,24,getResources().getDisplayMetrics()));
        a.recycle();
        //定義一個Paint,並支持抗鋸齒
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);


    }
    //在繪製控件時候會自動調用
    @Override
    protected void onDraw(Canvas canvas) {
        mWidth = getWidth();//獲取控件的寬度
        mHeight = getHeight();//獲取控件的高度
        mRectF = new RectF(0,0,mWidth,mHeight);
        //繪製圓角矩形邊框,但是發現,相對於在xml設置相同參數的shape,此處繪製會有明顯的不順滑,如有知道爲什麼的,請留言告知,謝謝
        //mPaint.setStyle(Paint.Style.STROKE);
        //mPaint.setColor(mBorderColor);
        //mPaint.setStrokeWidth(mBorderWidth);
        //canvas.drawRoundRect(mRectF,mBorderRadius,mBorderRadius,mPaint);

        //分割線
        float offset = mRectF.width() / mCodeLength;
        float lineX;
        mPaint.setStrokeWidth(1);
        for (int i=1;i<mCodeLength;i++){
            lineX = mRectF.left + offset * i;
            canvas.drawLine(lineX,0,lineX,mRectF.height(),mPaint);
        }

        mPaint.setColor(mCodeColor);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setTextSize(mCodeSize);
        mPaint.setTextAlign(Paint.Align.CENTER);
        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        float baseLine = (mRectF.bottom + mRectF.top - fontMetrics.bottom - fontMetrics.top)/2;
        float codeX;
        //更新數字
        for (int i=0;i<mTextLength;i++){
            codeX = mRectF.left + offset * i + offset / 2;
            canvas.drawText(mTextContent.substring(i,i+1),codeX,baseLine,mPaint);
        }

    }

    @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);
        this.mTextContent = text.toString();
        this.mTextLength = text.toString().length();
        invalidate();//當text改變的時候,重新繪製控件
    }
}

OK,控件寫完了,那看看如何使用

<com.hjy.verify.view.VerifyEditView
        android:id="@+id/edtTxtVerify"
        android:layout_width="match_parent"
        android:layout_height="46dp"
        android:layout_marginTop="25dp"
        android:layout_marginBottom="15dp"
        android:layout_marginLeft="40dp"
        android:layout_marginRight="40dp"
        android:background="@drawable/verify_border"
        android:cursorVisible="false"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:inputType="number"
        android:maxLength="6"
        app:VerifyBorderColor="@color/verifyBorderColor"
        app:VerifyBorderRadius="10dp"
        app:VerifyBorderWidth="1px"
        app:VerifyCodeLength="6"
        app:VerifyCodeTextColor="@color/verifyTextColor"
        app:VerifyCodeTextSize="24sp"/>

drawable目錄下的verify_border:

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="10dp" />
    <stroke android:color="@color/verifyBorderColor" android:width="1px" />
</shape>

代碼:https://github.com/DonnyHe/VerifyEditText

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章