[自定义控件]android自定义view基础

来源:互联网 发布:印度有帅哥吗 知乎 编辑:程序博客网 时间:2024/04/29 11:59

[自定义控件]android自定义view基础

尊重原创,转载请注明出处: http://blog.csdn.net/qq137722697

[自定义控件]android自定义view实战之太极图(传送门) ————>这是一篇自定view的实战文章

大部分的自定义view包括以下的步骤:

1、在style.xml文件中定义暴露的属性;

2、继承view或其子类,重写构造方法,获取;

[ 3、重写onMeasure方法,获取/设置控件的大小; ]

4、重写onDraw方法,实际的绘制逻辑。

第三步可以不走哦;

一、资源文件(style.xml)中定义可以暴露的属性

如下:

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="YZMView">        <attr name="text" format="string" />        <attr name="textSize" format="dimension" />        <attr name="textColor" format="color|reference" />    </declare-styleable></resources>

这里的format有下面的值:

1、reference:引用资源ID类型,如android:text=”@string/str_title”,str_title=“标题”;

2、color:颜色类型,如为字体设置颜色;

3、boolean:布尔类型,如设置是否显示;

4、dimension:尺寸大小类型,如设置字体的大小;

5、float:浮点类型,如设置透明度;

6、integer:整形类型,如设置时间间隔;

7、string:字符串类型,如设置字体内容;

8、fraction:百分数类型,如设置点的相对位置;

9、enum:枚举类型,如某个属性只能有几个固定的值;

10、flag:位或运算类型,如属性多选。

温馨提示:一个属性值可以设置多种类型。

二、继承view或其子类,重写构造方法,获取属性

在有三个参数的构造方法中使用TypedArray(属性类型数组来获取),TypedArray需要关联布局文件中的属性:attrs,defStyle为构造方法中的参数,直接使用即可,这里只需要传入自动一的属性资源R.styleable.YZMView

TypedArray arr=context.getTheme().obtainSyteleAttributes(attrs,R.styleable.YZMView,defStyle,0);

上面是映射属性,属性是需要拿来设置,如何拿呢?其实它已经存在TypedArray了

public class YZMView extends View {    private String text = "1234";    private float textSize = 48;    private int textColor = 0xFFFFFFFF;       public YZMView(Context context) {        this(context, null);    }    public YZMView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public YZMView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.YZMView, defStyleAttr, 0);        textSize = ta.getDimension(R.styleable.YZMView_textSize, 48);//16sp=48px默认16sp        textColor = ta.getColor(R.styleable.YZMView_textColor, 0xFFFFFFFF);        ta.recycle();//及时释放            }  }

三、重写onMeasure方法,获取/设置控件的大小

以下基本上是固定写法(当然有些view是不需要重写这个方法的):

    @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) {//如果用户设置了宽度为wrap_content,那么就要自己测量了            widthSize =200;//设置默认值        }        if (heightMode == MeasureSpec.AT_MOST) {//如果用户设置高度为wrap_content,也是要自己测量            heightSize =100;//设置默认值        }        setMeasuredDimension(widthSize, heightSize);//设置测量的宽度    }

测量大小的类型:

EXACTLY:设置了明确的值或者match_parent

AT_MOST:设置为warp_content

UNSPECLIFIED:想多大就多大,一般不用

如果使用自定义控件的地方使用了wrap_content,那么系统是默认的是测量全部,这里需要自己处理一下(就像上面的固定写法一样)

四、重写onDraw方法,实际的绘制逻辑

@Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);//这里需要调用父类的绘制方法,这样系统会为本view绘制一些基本通用属性,如背景颜色        canvas.drawText(text, getMeasuredWidth() / 2 - mRect.width() / 2, getMeasuredHeight() / 2 + mRect.height() / 2, mPaint);    }

Paint画笔对象

android中画笔工具叫Paint,它可以画任何几何图形、文字、bitmap、setAnitAlias(true)表示去掉齿轮。

Paint的Style有3种:

Paint.Style.FILL 填充内部

Paint.Style.FILL_AND_STROKE 填充内部和描边

Paint.Style.STROKE 描边

这里写图片描述

Paint详细介绍

http://blog.csdn.net/abcdef314159/article/details/51720686

关于重绘

控件重绘就是重新调用“onDraw()”【原理就是,使用view.postInvalidate()——>子线程中使用,view.invalidate()——>主线程中调用】方法触发onDraw()。

五、实例

下面用一个简单验证码的实例来进入自定义view

这里写图片描述

属性定义(res/style.xml):

<resources>    <declare-styleable name="YZMView">        <attr name="text" format="string|reference" />        <attr name="textSize" format="dimension" />        <attr name="textColor" format="color|reference" />    </declare-styleable>    </resources>

YZMView类:

/** * 自定义View-------验证码 * Created by HDL on 2017/2/5. */public class YZMView extends View {    private String text = "1234";    private float textSize = 48;    private int textColor = 0xFFFFFFFF;    private Paint mPaint;    private Rect mRect;    private static final String TAG = "YZMView";    public YZMView(Context context) {        this(context, null);    }    public YZMView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public YZMView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        createCode();        TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.YZMView, defStyleAttr, 0);        textSize = ta.getDimension(R.styleable.YZMView_textSize, 48);        textColor = ta.getColor(R.styleable.YZMView_textColor, 0xFFFFFFFF);        ta.recycle();//及时释放        this.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                createCode();                Log.e(TAG, "setOnClickListener: " + text);                postInvalidate();            }        });        mPaint = new Paint();        mPaint.setAntiAlias(true);//取消锯齿        mPaint.setTextSize(textSize);        Log.e(TAG, "YZMView: " + textColor);        mPaint.setColor(textColor);        mRect = new Rect();        mPaint.getTextBounds(text, 0, text.length(), mRect);//将text的边框赋值给mrect    }    /**     * 随机创建4位数字     */    private void createCode() {        text = "";        for (int i = 0; i < 4; i++) {            text += (int) (Math.random() * 10 - 1) + "";        }    }    public String getText() {        return text;    }    public void setText(String text) {        this.text = text;    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        canvas.drawText(text, getMeasuredWidth() / 2 - mRect.width() / 2 - 6.6f, getMeasuredHeight() / 2 + mRect.height() / 2, mPaint);//加6.6是因为有测量误差    }}

在布局文件中使用:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context="view.cusstom.hdl.com.customview.MainActivity">    <view.cusstom.hdl.com.customview.YZMView        android:id="@+id/yzm_main_code"        android:layout_width="80dp"        android:layout_height="40dp"        android:background="#c9c7c9"        app:textColor="#090a09"        app:textSize="30sp" />    <Button        android:layout_width="wrap_content"        android:text="校验"        android:onClick="onCheck"        android:layout_height="wrap_content" /></LinearLayout>

添加噪点的代码就很简单了,for循环画指定数量的点和线即可,这里就不贴了,网上一大堆。

觉得不错的话顶一个吧

尊重原创,转载请注明出处: http://blog.csdn.net/qq137722697

0 0