首先看看效果

如上图的密码输入框,没有密码时,有几个密码就有几条下划线,输入密码后显示的内容为“*”,并且底部就没有下划线了,同样有很多方式实现,这里就偷懒改改EditText来实现,所以需要做的就是画线、画“*”,代码很简单,偷懒也没有写attr,属性直接初始化写死了。这个思路同样适用于那些内容区域是方框的密码输入,就是画线和画矩形的区别。
1public class PasswordUnderLineEditText extends EditText { 2 3 public interface TextIndexChangeListener { 4 void onTextIndexChange(CharSequence text, int index); 5 } 6 7 private TextIndexChangeListener mTextIndexChangeListener; 8 9 @ColorInt 10 private int lineColor; 11 private int lineCount; 12 private int lineMargin; 13 private int lineHeight; 14 private int linePaddingBottom; 15 16 private String changedText; 17 private int changedTextSize; 18 private int changedTextColor; 19 private int textLength; 20 private boolean isHideLineOnChanged; 21 22 private Paint mLinePaint; 23 private TextPaint mChangedTextPaint; 24 25 26 public PasswordUnderLineEditText(Context context) { 27 this(context, null); 28 } 29 30 public PasswordUnderLineEditText(Context context, AttributeSet attrs) { 31 super(context, attrs); 32 lineColor = getResources().getColor(R.color.gray); 33 changedTextColor = getResources().getColor(R.color.black); 34 lineCount = 6; 35 changedTextSize = DensityUtil.sp2px(context, 20); 36 lineMargin = DensityUtil.dp2px(context, 12); 37 linePaddingBottom = DensityUtil.dp2px(context, 10); 38 lineHeight = DensityUtil.dp2px(context, 1); 39 40 changedText = "*"; 41 isHideLineOnChanged = true; 42 setGravity(Gravity.CENTER_VERTICAL); 43 setTextColor(getResources().getColor(android.R.color.transparent)); 44 setBackgroundColor(Color.WHITE); 45 setCursorVisible(false); 46 setInputType(InputType.TYPE_CLASS_NUMBER); 47 setFilters(new InputFilter[]{new InputFilter.LengthFilter(lineCount)}); 48 49 mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); 50 mLinePaint.setColor(lineColor); 51 mLinePaint.setStyle(Paint.Style.FILL); 52 mLinePaint.setStrokeWidth(lineHeight); 53 mChangedTextPaint = new TextPaint(); 54 mChangedTextPaint.setColor(changedTextColor); 55 mChangedTextPaint.setTextSize(changedTextSize); 56 mChangedTextPaint.setStyle(Paint.Style.FILL); 57 } 58 59 @Override 60 protected void onDraw(Canvas canvas) { 61 super.onDraw(canvas); 62 int height = getHeight(); 63 int width = getWidth(); 64 canvas.save(); 65 66 int singleLineWidth = width / lineCount; 67 int startX = 0; 68 int stopX = 0; 69 int startY = height - linePaddingBottom; 70 for (int i = 0; i < lineCount; i++) { 71 if (textLength == 0) { 72 startX = i * singleLineWidth + lineMargin; 73 stopX = (i + 1) * singleLineWidth - lineMargin; 74 canvas.drawLine(startX, startY, stopX, startY, mLinePaint); 75 } else if (textLength > 0) { 76 int changeIndex; 77 if (isHideLineOnChanged) { 78 changeIndex = textLength; 79 } else { 80 changeIndex = 0; 81 } 82 startX = (i + changeIndex) * singleLineWidth + lineMargin; 83 stopX = (i + changeIndex + 1) * singleLineWidth - lineMargin; 84 canvas.drawLine(startX, startY, stopX, startY, mLinePaint); 85 } 86 } 87 for (int i = 0; i < textLength; i++) { 88 startX = i * singleLineWidth + lineMargin; 89 stopX = (i + 1) * singleLineWidth - lineMargin; 90 canvas.drawText(changedText, (startX + stopX) / 2 - changedTextSize / 4, (height + changedTextSize) / 2, mChangedTextPaint); 91 } 92 93 canvas.restore(); 94 } 95 96 97 @Override 98 protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { 99 this.textLength = text.length(); 100 invalidate(); 101 if(mTextIndexChangeListener!=null){ 102 mTextIndexChangeListener.onTextIndexChange(text,textLength); 103 } 104 }