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;
}
@Override
public void setBackgroundColor(@ColorInt int color) {
if (bgPaint != null) {
bgPaint.setColor(color);
invalidate();
}
}
@Override
protected 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);
}
@Override
protected 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);
}
@Override
protected 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;
}
}
public interface OnInputCompletedListener {
void onComplete(String value, OnCheckResultCallback callback);
}
public interface OnCheckResultCallback {
void onCheckedResult(boolean result);
}
密码键盘:https://blog.csdn.net/TomCat0916/article/details/105751838
仿支付宝密码输入弹窗https://blog.csdn.net/TomCat0916/article/details/105776871