自定义控件之-----密码框
很多时候我们会使用到输入密码并隐藏显示,这里我仿照支付宝密码输入写了下面这个控件。
先看效果:
下面附上源码:
package com.lt.vs.come.custom; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; /** * Created by 金色VS时空 on 2018/2/19. */ public class PasswordInputView extends View { public PasswordInputView(Context context) { super(context); initPaint(); } public PasswordInputView(Context context, AttributeSet attrs) { super(context, attrs); initPaint(); } public PasswordInputView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initPaint(); } private void initPaint() { paint=new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(Color.BLACK);;//Color.parseColor("#000000") paint.setStrokeWidth(6f); paint.setAntiAlias(true); } private Paint paint; private int mHeight; /** * 线宽 */ private float strokeWidth=1.5f; /** * 获取用户输入了第几位密码,根据位数绘制圆点代替,默认没有输入为0,不会绘制圆点 */ private int numberPath=0; /** * passwordsBoxsNumbers 密码框数量,可动态设置,默认为6个,可根据需求更改 */ private int passwordsBoxsNumbers =6; public Paint getPaint() { return paint; } public void setPaint(Paint paint) { this.paint = paint; } public int getNumberPath() { return numberPath; } public void setNumberPath(int numberPath) { this.numberPath = numberPath; } private int radius=10; public void setRadius(int radius) { this.radius = radius; } public void setPasswordsBoxsNumbers(int passwordsBoxsNumbers) { this.passwordsBoxsNumbers = passwordsBoxsNumbers; } /** * 间隔宽度设置为高 * startX 初始X */ private int startX; /** * 间隔宽度设置为高 * startY 初始Y */ private int startY; private int endY; /** * centerCircleX 画圆点的中心点X坐标 */ private int centerCircleX; @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mHeight=getHeight(); int reHeight=mHeight*2/3;//控件内容高 int reWidth=reHeight*passwordsBoxsNumbers;//控件内容宽,是passwordsBoxsNumbers倍高 int distance =(getWidth()-reWidth)/2; startX=distance; startY=(mHeight-reHeight)/2; endY=mHeight-startY; paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(2*strokeWidth); //画粗外框矩形 canvas.drawRect(distance,startY,distance+reWidth,endY,paint); //画细竖线 for (int i = 0; i < passwordsBoxsNumbers-1 ; i++) { paint.setStrokeWidth(strokeWidth); startX+=reHeight; canvas.drawLine(startX,startY,startX,endY,paint); } //准备画圆点 paint.setStyle(Paint.Style.FILL); centerCircleX = distance+reHeight/2; for (int j = 0; j < numberPath; j++) { canvas.drawCircle(centerCircleX,mHeight/2,radius,paint); centerCircleX+=reHeight; } } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthMode=MeasureSpec.getMode(widthMeasureSpec); int widthSize=MeasureSpec.getSize(widthMeasureSpec); int heightMode=MeasureSpec.getMode(heightMeasureSpec); int heightSize=MeasureSpec.getSize(heightMeasureSpec); if (widthMode==MeasureSpec.AT_MOST&&heightMode==MeasureSpec.AT_MOST){ setMeasuredDimension(800,80); }else if (widthMode==MeasureSpec.AT_MOST) { setMeasuredDimension(800,heightSize); }else if (heightMeasureSpec==MeasureSpec.AT_MOST){ setMeasuredDimension(widthSize,80); } } }
另外,我们可能会需要使用自己的键盘而不是采用系统键盘。这里我做了简单的 密码输入控件。
控件效果如下:
贴出源码:
package com.lt.vs.come.custom; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import java.util.ArrayList; import java.util.List; /** * Created by 金色VS时空 on 2017/11/7. */ public class PasswordsInputKeyBoardView extends View { public PasswordsInputKeyBoardView(Context context) { super(context); } public PasswordsInputKeyBoardView(Context context, AttributeSet attrs) { super(context, attrs); } public PasswordsInputKeyBoardView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } /** * 需要绘制的资源数据 */ private String [] numbers={"1","2","3","4","5","6","7","8","9","n","0","×"}; /** * 行高 */ private float singleHeight; /** * 列宽 */ private float singleWidth; /** * 起始X,Y值,方便绘制网格线 */ private float startX; private float startY; /** * 绘制数字时的X位置 */ private float x; /** * 网格线颜色,和按下时背景颜色相同 */ private String gridLineOrPressColor="#cccccc"; /** * 数字颜色 */ private String textNumberColor="#000000"; /** * 默认背景颜色 */ private String defaultBackgroundColor="#ffffff"; public void setDefaultBackgroundColor(String defaultBackgroundColor) { this.defaultBackgroundColor = defaultBackgroundColor; } /** * 绘制数字大小 */ private int textSize=60; /** * 网格线宽 */ private float strokeWidth=1.5f; public void setNumbers(String[] numbers) { this.numbers = numbers; } public void setGridLineOrPressColor(String gridLineOrPressColor) { this.gridLineOrPressColor = gridLineOrPressColor; } public void setTextNumberColor(String textNumberColor) { this.textNumberColor = textNumberColor; } public void setTextSize(int textSize) { this.textSize = textSize; } public void setStrokeWidth(float strokeWidth) { this.strokeWidth = strokeWidth; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); initPaint(canvas); singleWidth=getWidth()/3; singleHeight=getHeight()/4; //画背景颜色 mPaint.setColor(Color.parseColor(defaultBackgroundColor)); mPaint.setStyle(Paint.Style.FILL); canvas.drawRect(0,0,getWidth(),getHeight(),mPaint); //根据是否按下,变换背景颜色 if (isPressed){ mPaint.setColor(Color.parseColor(gridLineOrPressColor)); mPaint.setStyle(Paint.Style.FILL); //绘制按下时背景(按下的那一格) canvas.drawRect((float)pressedRectPosition.get(0),(float)pressedRectPosition.get(1), (float)pressedRectPosition.get(2),(float)pressedRectPosition.get(3),mPaint); }else if (pressedRectPosition!=null&&pressedRectPosition.size()!=0){ mPaint.setColor(Color.parseColor(defaultBackgroundColor)); mPaint.setStyle(Paint.Style.FILL); //绘制离开时背景(按下的那一格) canvas.drawRect((float)pressedRectPosition.get(0),(float)pressedRectPosition.get(1), (float)pressedRectPosition.get(2),(float)pressedRectPosition.get(3),mPaint); pressedRectPosition.clear(); } mPaint.setColor(Color.parseColor(gridLineOrPressColor)); for (int i = 0; i < 5 ; i++) { //画横线 canvas.drawLine(startX,startY,startX+getWidth(),startY,mPaint); startY+=singleHeight; } //重置 startX=0; startY=0; for (int j = 0; j < 4 ; j++) { //画竖线 canvas.drawLine(startX,startY,startX,startY+getHeight(),mPaint); startX+=singleWidth; //画数据 } //重置 startX=0; startY=0; float y=0; mPaint.setColor(Color.parseColor(textNumberColor)); mPaint.setFakeBoldText(true); mPaint.setTextSize(textSize); for (int i = 0; i < 4 ; i++) { //画数据,一行一行画 for (int j = 0; j < 3; j++) { if (j==0){ //获取文字宽 float textWidth=mPaint.measureText(numbers[i*3+j]); x=singleWidth/2-textWidth/2; } if (i==0){ //获取文字高 Rect re=new Rect(); mPaint.getTextBounds(numbers[i*3+j],0,1,re); int textHeight=re.height(); y=singleHeight/2+textHeight/2; } if (!numbers[i*3+j].equals("n")){ canvas.drawText(numbers[i*3+j],x,y,mPaint); } //X内层变化(放里面) x+=singleWidth; } //Y外层变化(放外面) y+=singleHeight; } } private Paint mPaint; private void initPaint(Canvas canvas) { mPaint=new Paint(); mPaint.setStrokeWidth(strokeWidth); mPaint.setAntiAlias(true); } //是否按下 private boolean isPressed=false; // //表示记录按下时所在矩形框位置的集合 private List pressedRectPosition=new ArrayList(); @Override public boolean onTouchEvent(MotionEvent event) { int action=event.getAction(); switch(action){ case MotionEvent.ACTION_DOWN: //记录按下时刻的X,Y float downX=event.getX(); float downY=event.getY(); //边界值 (left,top,right,bottom)对应(minX,minY,maxX,maxY) float minX=0; float minY=0; float maxX=getWidth()/3; float maxY=getHeight()/4; for (int i = 0; i < 4; i++) { //确定点击事件所在行 if (maxY>downY&&downY>minY){ for (int j = 0; j < 3; j++) { //确定点击事件所在列 if (maxX>downX&&downX>minX&&(i*3+j)!=9){ mOnNumberSelectedListener.onNumberSelected(numbers[i*3+j]); //按下是所在矩形位置 (minX,minY,maxX,maxY); //按下状态为true isPressed=true; pressedRectPosition.add(minX); pressedRectPosition.add(minY); pressedRectPosition.add(maxX); pressedRectPosition.add(maxY); invalidate(); } minX=maxX; maxX=maxX+singleWidth; } } minY=maxY; maxY=maxY+singleHeight; } break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: isPressed=false; invalidate(); break; } return true; } private OnNumberSelectedListener mOnNumberSelectedListener; public void setmOnNumberSelectedListener(OnNumberSelectedListener mOnNumberSelectedListener) { this.mOnNumberSelectedListener = mOnNumberSelectedListener; } /** * 点击事件接口 */ public interface OnNumberSelectedListener{ void onNumberSelected(String numberStr); } }
两控件可结合使用,源码已提供接口。