前言:感覺自己記憶力不是很好,很多寫過的東西容易忘記,所以還是寫個博客記錄一下,菜鳥一枚,望各位師傅指點。
嘿喂狗,來看我們要實現的效果(如果你說:”開發之前當然看不到效果,看個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>