自定义view实现密码输入框
2020-07-05 本文已影响0人
crush_d872
最近项目中 有这样的一个需求 直接贴图了
image.png image.png
正好通过这个需求重新复习一下自定义view。
分析需求:
像这种样式,还带有输入框,那么我们第一时间想到的是继承自EditText,这个问题我们确认下来,接下来就是一些绘制的步骤了,大概讲一下绘制的一些步骤:
1.先绘制出四条线:这个主要还是根据需求走,如果你想自定义一个完美的控件,那么你可以自定义属性,在属性中自定义这个数目,然后去绘制,
2.线我们绘制好了 ,接下来其实就是把文字绘制上去了,edittext有自带的文字监听事件,我们可以通过这个事件,来把我们的文字绘制上去
3.我们看到第二张图,每次未输入的框下方的下划线 都是会变色的,所以在每次输入一个文字时 ,我们要把下一个文字框变色
需求分析完了现在我们开始动手把这个东西完善
我们自定义view主要有三个步骤:
测量、摆放,绘制
这个需求中我们应该是用不到摆放这个过程
接下来就是重点动手的时候了,建议自己先动手写一写,这样以后遇到自定义view就不虚了
1.测量
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int height = 0;
switch (heightMode){
case MeasureSpec.UNSPECIFIED: //如果指定了这两种模式,就需要自己去指定高度,
case MeasureSpec.AT_MOST: //因为宽度是不会变化的, 至于为什么高度会变化,绘制的时候我们会讲这个
height = sp2px(getContext(),30) + dip2px(1) + 10;
break;
case MeasureSpec.EXACTLY:
height = MeasureSpec.getSize(heightMeasureSpec);
break;
}
setMeasuredDimension(width,height);
}
在计算高度时,当测量模式为MeasureSpec.UNSPECIFIED,MeasureSpec.AT_MOST时,第一项计算的是文字的高度,第二项是底部横线的高度,第三项是底部横线到文字的距离,这些属性都可以自定义到属性当中,我这里就直接写数字了
2.绘制
@Override
protected void onDraw(Canvas canvas) {
mBottomWidth = getWidth()/4; //底部线的长度
for (int i=0;i<4;i++){
int startX;
int endX;
//绘制底部横线的逻辑,输入第一个亮起下一个,主要是更换画笔的颜色
startX = mBottomWidth*(i)+dip2px(5);
endX = mBottomWidth *(1+i)-dip2px(5);
Rect rectF = new Rect(startX,getHeight()-mBottomHeight,endX,getHeight());
canvas.drawRect(rectF,i <= textLength ? mSelectPaint : mUnSelectPaint);
}
//绘制文字
for (int i=0;i<textLength;i++){
String child = String.valueOf(mText.charAt(i));//
Rect rect = new Rect(mBottomWidth*i,0,mBottomWidth*(i+1),getHeight()-mBottomHeight);
drawText(canvas,child,rect);
}
}
private void drawText(Canvas canvas,String str,Rect rect){
Rect mTextRect = new Rect();
mTextPaint.getTextBounds(str,0,1,mTextRect);
Paint.FontMetricsInt fontMetricsInt = mTextPaint.getFontMetricsInt();
int baseline = rect.centerY()- (fontMetricsInt.top+fontMetricsInt.bottom)/2 - 10;
canvas.drawText(str,rect.centerX()-mTextRect.width()/2,baseline,mTextPaint);
}
@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
this.textLength = text.length();
this.mText = text.toString();
invalidate();
}
还有个小问题 在我们第一次调起这个页面时,需要自动弹起键盘,
private void initPaint(){
//自动弹出软键盘
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
InputMethodManager inputManager =
(InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.showSoftInput(PasswordEditText.this, 0);
}
}, 400);
mSelectPaint = new Paint();
mSelectPaint.setColor(getResources().getColor(R.color.color_ff345a));
mSelectPaint.setAntiAlias(true);
mSelectPaint.setStyle(Paint.Style.FILL);
mUnSelectPaint = new Paint();
mUnSelectPaint.setColor(getResources().getColor(R.color.color_e5e5e5));
mUnSelectPaint.setAntiAlias(true);
mUnSelectPaint.setStyle(Paint.Style.FILL);
mTextPaint = new Paint();
mTextPaint.setColor(getResources().getColor(R.color.color_000000));
mTextPaint.setTextSize(sp2px(getContext(),30));
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setAntiAlias(true);
}
所以在初始化时就把这个操作做了,另外我们点击我们的自定义view时也需要调起键盘,
@Override
public boolean onTouchEvent(MotionEvent event) {
InputMethodManager inputManager = (InputMethodManager)getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.showSoftInput(this, 0);
return super.onTouchEvent(event);
}
这样这个自定义view就结束了,很简单的自定义view,有很多细节的地方可以自己去优化,比如自定义属性等一些问题。