先看效果:
特点:
例如:
1、 一个自定义view去实现,避免代码浪费
2、 对外暴露每次变化后的结果,方便调用
注意:
这种view一般需要注意以下几点
1、 把点击区域,当做变量,去分情况绘制
2、 注意判断点击区域
3、 注意文字居中,和宽高美观处理
用法:
//TODO 你也可以继续去改变此view,让更加灵活,我是懒得去写了,实现业务功能就行
mypass=(MyPassWordView)findViewById(R.id.mypass);
mypass.setonBar(new MyPassWordView.OnBarLisenter() {
@Override
public void onChoose(ArrayList<String> data) {
//data即为已经输入的数字
}
});
代码:
public class MyPassWordView extends View {
private Paint circlePaint,textPaint;
private int circleWidth=0;
private int nowX=-1,nowY=-1;
private ArrayList<String> pas=new ArrayList<>();
public MyPassWordView(Context context) {
super(context);
initData();
}
public MyPassWordView(Context context, AttributeSet attrs) {
super(context, attrs);
initData();
}
public MyPassWordView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initData();
}
private void initData(){
textPaint=new Paint();
textPaint.setStyle(Paint.Style.FILL);
textPaint.setColor(0xff000000);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setAntiAlias(true);//抗锯齿
circleWidth=BaseObserver.getInstance().getPXformDP(1);
circlePaint=new Paint();
circlePaint.setStyle(Paint.Style.STROKE);//空心效果
circlePaint.setStrokeWidth(circleWidth);
circlePaint.setColor(0xff000000);
circlePaint.setAntiAlias(true);//抗锯齿
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int w=getWidth();
int h=getHeight();
int oneW=w/3;
int oneH=h/4;
for(int i=0;i<4;i++){
for(int j=0;j<3;j++){
int left=oneW*j;
int top=oneH*i;
int right=oneW*j+oneW;
int bottom=oneH*i+oneH;
int radius=0;
//半径去短边的4/5,比较美观一点
if(oneW>oneH){
radius=(oneH/2)/5*4;
}else {
radius=(oneW/2)/5*4;
}
textPaint.setTextSize(radius);
//中心点
int x=left+oneW/2;
int y=top+oneH/2;
//计算显示的文字
String now="";
if(i!=3){
now=(i*3+j+1)+"";
}else {
if(j==0){
now="";
}else if(j==1){
now="0";
}else {
now="C";
}
}
//点击区域是否在园内
boolean isInside=false;
int nowR=(int)Math.sqrt((x-nowX)*(x-nowX)+(y-nowY)*(y-nowY));
if(nowR<radius){
isInside=true;
}
//根据状态绘制圆和文字
if(isInside){
circlePaint.setStyle(Paint.Style.FILL_AND_STROKE);
textPaint.setColor(0xffffffff);
}else {
circlePaint.setStyle(Paint.Style.STROKE);
textPaint.setColor(0xff000000);
}
if(i==3&&j==0){
//不绘制左下角那个
}else {
canvas.drawCircle(x,y,(radius-circleWidth),circlePaint);
float baseLineY =y+ (Math.abs(textPaint.ascent() + textPaint.descent()) / 2);
canvas.drawText(now, x,baseLineY, textPaint);
if(isInside){
tell(i,j);
}
}
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN://按下
nowX=(int)x;
nowY=(int)y;
invalidate();
break;
case MotionEvent.ACTION_MOVE://移动
break;
case MotionEvent.ACTION_UP://松开
nowX=-1;
nowY=-1;
invalidate();
break;
}
return true;
}
private void tell(int ii,int jj){
if(ii==3){
if(jj==0){
}else if(jj==1){
pas.add("0");
}else {
pas.clear();
}
}else {
int code=(ii*3)+jj+1;
pas.add(""+code);
}
lisenter.onChoose(pas);
}
public interface OnBarLisenter{
void onChoose(ArrayList<String> s);
}
private OnBarLisenter lisenter;
public void setonBar(OnBarLisenter lisenter){
this.lisenter=lisenter;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = getMySize(600, widthMeasureSpec);
int height = getMySize(600,heightMeasureSpec);
setMeasuredDimension(width, (int)height);
}
protected int getMySize(int def,int measureSpec ) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
return specSize;
}
if (specMode == MeasureSpec.AT_MOST) {
return specSize;
}
return def;
}
}