android自定义View基础系列一(点击随机生成验证码效果)

来源:互联网 发布:聊城关键词优化 编辑:程序博客网 时间:2024/06/13 07:23

前言:

写了几篇博文,说实话自己很不满意,都觉得很空洞,写的也不是很好,只能硬着头皮继续写,写多了希望能好些,这一系列都是基础+练手系列,大神无视,不管怎么样,希望能对大家有点帮助吧。

本系列主要是介绍一些使用绘制view方式来自定义view实现的一些效果,很多是我之前学别人实现的一些效果,作为基础入门篇。

概要:

记得之前学习hy大神的博文,大神说自定义VIew三大步骤:

1)自定义View的属性;

2)在构造方法中获取到属性;

3)重写onMeasure,onDraw,onLayout方法。

我一直秉承着大神的意志学习前进着,觉得还是蛮有用的,至少不会无从下手。本文将实现一个类似点击随机生成验证码的效果,比较简单。效果如图:


正文:

首先分析下我们会用到的属性,这里需要用到按钮背景色,文字颜色,字体大小。现在我们开始自定义属性,在values文件夹下创建一个attrs.xml文件,在里面定义我们的属性,声明我们的样式。

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="MyViewAttrs">        <attr name="bgColor" format="color">#dddddd</attr>        <attr name="textColor" format="color">#ff0000</attr>        <attr name="textSize" format="dimension">30</attr>    </declare-styleable></resources>
这里format是取值类型。有:string,color,demension,integer,enum,reference,float,boolean,fraction,flag。

现在声明自定义View,在布局文件中引入自定义View。

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:custom="http://schemas.android.com/apk/res/com.example.liujibin.testmyview1"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.example.liujibin.testmyview1.MainActivity">    <com.example.liujibin.testmyview1.MyView        android:layout_width="wrap_content"        android:layout_height="wrap_content" /></RelativeLayout>
在声明的View中重写构造函数,这里因为要获取属性,所以我们设置默认调用含三个参数的构造函数。

public class MyView extends View {    //背景色    private int bgColor;    //文字色    private int textColor;    //文字大小    private int textSize;    public MyView(Context context) {        this(context,null);    }    public MyView(Context context, AttributeSet attrs) {        this(context, attrs,0);    }    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.MyViewAttrs,defStyleAttr,0);        bgColor = ta.getColor(R.styleable.MyViewAttrs_bgColor, Color.BLACK);        textColor = ta.getColor(R.styleable.MyViewAttrs_textColor,Color.WHITE);        textSize = ta.getDimensionPixelSize(R.styleable.MyViewAttrs_textSize,30);        ta.recycle();    }}
TypedArray要记得释放。

然后重写onMeasure,onDraw,这里用不到onLayout。绘制View,还需要画笔(Paint)和画布(Canvas),画布在onDraw中有封装,直接用就好了,我们自己创建一个Paint对象。因为要在指定区域内绘制文字,所以我们还需要创建Rect对象,在构造函数中实例化,不要在onDraw中实例化。

private Paint paint;private Rect r;

paint = new Paint();r = new Rect();
下面我们先来设置画笔属性,绘制背景框:

@Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //绘制矩形区域        paint.setColor(bgColor);        paint.setStrokeWidth(3);        paint.setAntiAlias(true);        canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),paint);    }


效果如图:



我们发现这个区域是全屏的,我们不需要这么大,只需要按钮大小,此时就需要用到onMeasure了。根据模式设置默认大小。

@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.EXACTLY){        }else{            widthSize = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,300,getResources().getDisplayMetrics());        }        if(heightMode == MeasureSpec.EXACTLY){        }else{            heightSize = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,200,getResources().getDisplayMetrics());        }        setMeasuredDimension(widthSize,heightSize);    }
此时效果:


然后我们需要给画笔设置文字,设置字体,获取文字的宽高。

private String str = "4232";

//获取文字宽高,绘制文字paint.setTextSize(textSize);paint.setColor(textColor);paint.getTextBounds(str,0,str.length(),r);canvas.drawText(str,getWidth()/2-r.width()/2,getHeight()/2+r.height()/2,paint);

效果如图:



下面需要实现点击变化文字,实现View的点击事件,我们这里取四位随机数,然后点击后设置给绘制的字符串。

//生成随机字符串    private String changeText(){        Random random = new Random();        String num = "";        for(int i = 0;i < 4;i++){            num = num + random.nextInt(10);        }        return num;    }
现在我们要的效果就实现了。

附上全部View的代码:

public class MyView extends View implements View.OnClickListener{    //背景色    private int bgColor;    //文字色    private int textColor;    //文字大小    private int textSize;    private Paint paint;    private Rect r;    private String str = "4232";    public MyView(Context context) {        this(context,null);    }    public MyView(Context context, AttributeSet attrs) {        this(context, attrs,0);    }    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.MyViewAttrs,defStyleAttr,0);        bgColor = ta.getColor(R.styleable.MyViewAttrs_bgColor, Color.BLACK);        textColor = ta.getColor(R.styleable.MyViewAttrs_textColor,Color.WHITE);        textSize = ta.getDimensionPixelSize(R.styleable.MyViewAttrs_textSize,(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,                30,getResources().getDisplayMetrics()));        ta.recycle();        setOnClickListener(this);        paint = new Paint();        r = new Rect();    }    @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.EXACTLY){        }else{            widthSize = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,200,getResources().getDisplayMetrics());        }        if(heightMode == MeasureSpec.EXACTLY){        }else{            heightSize = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,100,getResources().getDisplayMetrics());        }        setMeasuredDimension(widthSize,heightSize);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //绘制矩形区域        paint.setColor(bgColor);        paint.setStrokeWidth(3);        paint.setAntiAlias(true);        canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),paint);        //获取文字宽高,绘制文字        paint.setTextSize(textSize);        paint.setColor(textColor);        paint.getTextBounds(str,0,str.length(),r);        canvas.drawText(str,getWidth()/2-r.width()/2,getHeight()/2+r.height()/2,paint);    }    //生成随机字符串    private String changeText(){        Random random = new Random();        String num = "";        for(int i = 0;i < 4;i++){            num = num + random.nextInt(10);        }        return num;    }    @Override    public void onClick(View view) {        str = changeText();        invalidate();    }}







0 0
原创粉丝点击