自定义密码输入框
效果图


PasswordEditText
public class PasswordEditText extends AppCompatEditText {private Paint borderPaint;private Paint bgPaint;private float borderWidth;private float borderRadius;private int passwordLength;//密码长度==文本输入长度private int measuredHeight;private float averageWidth;//单个密码框宽度private RectF bgRectF;private RectF textRectF;private int textLength;//输入文本长度private CharSequence text;//输入的文本private boolean isPasswordVisible;//是否明文显示private String passwordReplaceText;//密文替代字符 isPasswordVisible= true可用private int borderSpace;//密码框间距 为0 外边框为整体单个密码框使用线条分割 不为0 单个密码框都有边框private OnInputCompletedListener completedListener;public PasswordEditText(Context context) {this(context, null);}public PasswordEditText(Context context, AttributeSet attrs) {this(context, attrs, 0);}public PasswordEditText(final Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PasswordEditText);borderWidth = typedArray.getDimensionPixelSize(R.styleable.PasswordEditText_borderWidth, 1);int borderColor = typedArray.getColor(R.styleable.PasswordEditText_borderColor, Color.BLACK);borderRadius = typedArray.getDimensionPixelSize(R.styleable.PasswordEditText_borderRadius, BaseUtils.dip2px(2));borderSpace = typedArray.getDimensionPixelSize(R.styleable.PasswordEditText_borderSpace, 0);int color = typedArray.getColor(R.styleable.PasswordEditText_android_background, Color.TRANSPARENT);passwordLength = typedArray.getInt(R.styleable.PasswordEditText_android_maxLength, 6);isPasswordVisible = typedArray.getBoolean(R.styleable.PasswordEditText_passwordVisible, true);String s = typedArray.getString(R.styleable.PasswordEditText_passwordReplaceText);passwordReplaceText = TextUtils.isEmpty(s) ? "*" : s;typedArray.recycle();setSingleLine();setBackground(null);super.setBackgroundColor(Color.TRANSPARENT);borderPaint = new Paint();borderPaint.setAntiAlias(false);borderPaint.setStyle(Paint.Style.STROKE);borderPaint.setStrokeWidth(borderWidth);borderPaint.setColor(borderColor);bgPaint = new Paint();bgPaint.setAntiAlias(false);bgPaint.setColor(color);bgPaint.setStrokeWidth(2);bgRectF = new RectF();textRectF = new RectF();}public void setBorderColor(@ColorInt int color) {if (borderPaint != null) {borderPaint.setColor(color);invalidate();}}public void setBorderWidth(int dp) {if (borderPaint != null) {borderWidth = BaseUtils.dip2px(dp);borderPaint.setStrokeWidth(borderWidth);invalidate();}}public void setBorderRadius(int dp) {borderRadius = BaseUtils.dip2px(dp);invalidate();}public void setPasswordLength(int length) {passwordLength = length;invalidate();}public void setPasswordVisible(boolean isVisible) {isPasswordVisible = isVisible;invalidate();}public void setPasswordReplaceText(String s) {if (!TextUtils.isEmpty(s)) {passwordReplaceText = s;invalidate();}}public int getPasswordLength() {return passwordLength;}public int getTextLength() {return textLength;}@Overridepublic void setBackgroundColor(@ColorInt int color) {if (bgPaint != null) {bgPaint.setColor(color);invalidate();}}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);int measuredWidth = getMeasuredWidth();measuredHeight = getMeasuredHeight();bgRectF = new RectF(0, 0, measuredWidth, measuredHeight);averageWidth = (measuredWidth - (passwordLength - 1) * borderSpace) / (passwordLength * 1f);}@Overrideprotected void onDraw(Canvas canvas) {drawBorder(canvas);drawText(canvas);}/*** 绘制密码*/private void drawText(Canvas canvas) {for (int i = 0; i < textLength; i++) {if (textRectF == null) {return;}initTextRectF(i);TextPaint paint = getPaint();paint.setTextAlign(Paint.Align.CENTER);Paint.FontMetrics fontMetrics = paint.getFontMetrics();if (fontMetrics != null && textRectF != null) {float dy = (fontMetrics.descent - fontMetrics.ascent) / 2 - fontMetrics.descent;int baseYLine = (int) (textRectF.centerY() + dy);String s = isPasswordVisible ? String.valueOf(text.charAt(i)) : passwordReplaceText;canvas.drawText(s, textRectF.centerX(), baseYLine, paint);}}}private void initTextRectF(int i) {float startX = (averageWidth + borderSpace) * i + borderWidth / 2f;float stopX = averageWidth + startX - borderWidth;textRectF.set(startX, borderWidth / 2f, stopX, measuredHeight - borderWidth / 2f);}/*** 绘制边框*/private void drawBorder(Canvas canvas) {if (borderSpace == 0) {drawBg(canvas, bgRectF);for (int i = 1; i < passwordLength; i++) {float startX = averageWidth * i;canvas.drawLine(startX, bgRectF.top, startX, measuredHeight, borderPaint);}} else {for (int i = 0; i < passwordLength; i++) {initTextRectF(i);drawBg(canvas, textRectF);}}}private void drawBg(Canvas canvas, RectF bgRectF) {canvas.drawRoundRect(bgRectF, borderRadius, borderRadius, bgPaint);canvas.drawRoundRect(bgRectF, borderRadius, borderRadius, borderPaint);}@Overrideprotected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {this.text = text;super.onTextChanged(text, start, lengthBefore, lengthAfter);if (text != null) {this.textLength = text.toString().length();invalidate();if (textLength >= passwordLength && completedListener != null) {completedListener.onComplete(text.toString(), null);}}}public void setOnInputCompletedListener(OnInputCompletedListener completedListener) {this.completedListener = completedListener;}
}
attrs.xml
<declare-styleable name="PasswordEditText"><attr name="borderWidth" format="dimension" /><attr name="borderColor" format="color" /><attr name="borderSpace" format="dimension" /><attr name="borderRadius" format="dimension" /><attr name="passwordVisible" format="boolean" /><attr name="passwordReplaceText" format="string" /><attr name="android:background" /><attr name="android:maxLength" /></declare-styleable>
OnInputCompletedListener
public interface OnInputCompletedListener {void onComplete(String value, OnCheckResultCallback callback);
}
OnCheckResultCallback
public interface OnCheckResultCallback {void onCheckedResult(boolean result);
}
密码键盘:https://blog.csdn.net/TomCat0916/article/details/105751838
仿支付宝密码输入弹窗https://blog.csdn.net/TomCat0916/article/details/105776871