自定义view三:输入六位验证码的控件
public class InputCodeView extends AppCompatEditText {
private int currentColor = 0xFFCCCCCC;
private int borderColor = 0xFFCCCCCC;
private float borderWidth = 5;
private float borderRadius = 3;
private int passwordLength = 6;
private int passwordColor = 0xFFCCCCCC;
private float passwordWidth = 8;
private float passwordRadius = 3;
private Paint passwordPaint = new Paint();
private Paint borderPaint = new Paint();
private int textLength;
private String textContent;
private float splitLineWidth = 0; //分割宽度
private float eachPasswordWidth = 0; //每个方块的宽度
private Path mPath = new Path();
private boolean passwordBold = false;
private String curPassword;
public InputCodeView(Context context, AttributeSet attrs) {
super(context, attrs);
DisplayMetrics dm = getResources().getDisplayMetrics();
borderWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, borderWidth, dm);
borderRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, borderRadius, dm);
passwordLength = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, passwordLength, dm);
passwordWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, passwordWidth, dm);
passwordRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, passwordRadius, dm);
splitLineWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, splitLineWidth, dm);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.InputCodeView, 0, 0);
currentColor = a.getColor(R.styleable.InputCodeView_pivCurrentColor, borderColor);
borderColor = a.getColor(R.styleable.InputCodeView_pivBorderColor, borderColor);
borderWidth = a.getDimension(R.styleable.InputCodeView_pivBorderWidth, borderWidth);
borderRadius = a.getDimension(R.styleable.InputCodeView_pivBorderRadius, borderRadius);
passwordLength = a.getInt(R.styleable.InputCodeView_pivPasswordLength, passwordLength);
passwordColor = a.getColor(R.styleable.InputCodeView_pivPasswordColor, passwordColor);
passwordWidth = a.getDimension(R.styleable.InputCodeView_pivPasswordWidth, passwordWidth);
passwordRadius = a.getDimension(R.styleable.InputCodeView_pivPasswordRadius, passwordRadius);
splitLineWidth = a.getDimension(R.styleable.InputCodeView_pivSplitLineWidth, splitLineWidth);
passwordBold = a.getBoolean(R.styleable.InputCodeView_pivPasswordBold, false);
a.recycle();
borderPaint.setStrokeWidth(borderWidth);
borderPaint.setColor(borderColor);
borderPaint.setStyle(Paint.Style.FILL);
passwordPaint.setStrokeWidth(passwordWidth);
passwordPaint.setTypeface(Typeface.DEFAULT);
if (passwordBold)
passwordPaint.setStyle(Paint.Style.STROKE);
else passwordPaint.setStyle(Paint.Style.FILL);
passwordPaint.setColor(passwordColor);
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) {
}
@Override
public void afterTextChanged(Editable s) {
curPassword = s.toString();
if (!TextUtils.isEmpty(curPassword) && passwordLength == curPassword.length()) {
if (mOnExaminedCodeListener != null) {
mOnExaminedCodeListener.onExaminedCode(curPassword);
}
}
}
});
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width_size = MeasureSpec.getSize(widthMeasureSpec);
int width_mode = MeasureSpec.getMode(widthMeasureSpec);
int height_mode = MeasureSpec.getMode(heightMeasureSpec);
int height_size = MeasureSpec.getSize(widthMeasureSpec);
int widthSpec = MeasureSpec.makeMeasureSpec(width_size, width_mode);
if (width_size / passwordLength - height_size < 20) {
splitLineWidth = 20;
int heightSpec = MeasureSpec.makeMeasureSpec(width_size / passwordLength - 20, MeasureSpec.EXACTLY);
super.onMeasure(widthSpec, heightSpec);
} else {
super.onMeasure(widthSpec, heightMeasureSpec);
}
}
@Override
@SuppressLint("DrawAllocation")
protected void onDraw(Canvas canvas) {
int width = getWidth();
int height = getHeight();
if (width / passwordLength - height < 20) {
splitLineWidth = 20;
} else {
eachPasswordWidth = height;
splitLineWidth = (width - passwordLength * eachPasswordWidth) / (passwordLength - 1);
}
eachPasswordWidth = (width - (passwordLength - 1) * splitLineWidth) / passwordLength;
for (int i = 0; i < passwordLength; i++) {
RectF rectIn = new RectF(i * (eachPasswordWidth + splitLineWidth) + 1, 1, (i + 1) * eachPasswordWidth + i * splitLineWidth, height);
canvas.drawRoundRect(rectIn, borderRadius, borderRadius, borderPaint);
// if (!TextUtils.isEmpty(curPassword)) {
// if (i < curPassword.length()) borderPaint.setColor(currentColor);
// else borderPaint.setColor(borderColor);
// }
// mPath = new Path();
// mPath.moveTo(i * (eachPasswordWidth + splitLineWidth) + dp2px(6), getMeasuredHeight() - dp2px(1));
// mPath.lineTo((i + 1) * eachPasswordWidth + i * splitLineWidth - dp2px(6), getMeasuredHeight() - dp2px(1));
// canvas.drawPath(mPath, borderPaint);
}
// 密码
float cx, cy = height / 2;
passwordPaint.setColor(passwordColor);
float textSize = getTextSize();
passwordPaint.setTextSize(textSize);
passwordPaint.setAntiAlias(true);
float half = (width - (passwordLength - 1) * splitLineWidth) / passwordLength / 2;
for (int i = 0; i < textLength; i++) {
cx = i * (eachPasswordWidth + splitLineWidth) + half;
String text = textContent.substring(i, i + 1);
Rect bounds = new Rect();
passwordPaint.getTextBounds(text, 0, text.length(), bounds);
canvas.drawText(text, cx - bounds.width() / 2, cy + bounds.height() / 2, passwordPaint);
}
}
@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
this.textLength = text.toString().length();
textContent = text.toString();
invalidate();
}
public int getBorderColor() {
return borderColor;
}
public void setBorderColor(int borderColor) {
this.borderColor = borderColor;
borderPaint.setColor(borderColor);
invalidate();
}
public float getBorderWidth() {
return borderWidth;
}
public void setBorderWidth(float borderWidth) {
this.borderWidth = borderWidth;
borderPaint.setStrokeWidth(borderWidth);
invalidate();
}
public float getBorderRadius() {
return borderRadius;
}
public void setBorderRadius(float borderRadius) {
this.borderRadius = borderRadius;
invalidate();
}
public int getPasswordLength() {
return passwordLength;
}
public void setPasswordLength(int passwordLength) {
this.passwordLength = passwordLength;
invalidate();
}
public int getPasswordColor() {
return passwordColor;
}
public void setPasswordColor(int passwordColor) {
this.passwordColor = passwordColor;
passwordPaint.setColor(passwordColor);
invalidate();
}
public float getPasswordWidth() {
return passwordWidth;
}
public void setPasswordWidth(float passwordWidth) {
this.passwordWidth = passwordWidth;
passwordPaint.setStrokeWidth(passwordWidth);
invalidate();
}
public float getPasswordRadius() {
return passwordRadius;
}
public void setPasswordRadius(float passwordRadius) {
this.passwordRadius = passwordRadius;
invalidate();
}
private int dp2px(int dp) {
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
return (int) (dp * displayMetrics.density + 0.5f);
}
/**
* 设置验证码完成回调接口
*/
public interface OnExaminedCodeListener {
void onExaminedCode(String identified_code);
}
private OnExaminedCodeListener mOnExaminedCodeListener;
public void setOnExaminedCodeListener(OnExaminedCodeListener examinedCodeListener) {
this.mOnExaminedCodeListener = examinedCodeListener;
}
}
attrs文件
<declare-styleable name="InputCodeView">
<attr name="pivBorderColor" format="color" />
<attr name="pivBorderWidth" format="dimension" />
<attr name="pivBorderRadius" format="dimension" />
<attr name="pivPasswordColor" format="color" />
<attr name="pivPasswordWidth" format="dimension" />
<attr name="pivPasswordRadius" format="dimension" />
<attr name="pivPasswordLength" format="integer" />
<attr name="pivSplitLineWidth" format="dimension" />
<attr name="pivPasswordBold" format="boolean" />
<attr name="pivCurrentColor" format="reference|color" />
</declare-styleable>