自定义View注意事项

强颜欢笑 提交于 2020-02-26 16:48:34

一、自定义view需要继承View类

既然是自定义view所以为了方便需要继承View类,或者其他View类例如TextView等类

二、必须写入构造方法否则无法使用findViewbyId()方法找到控件

之定义View必须写入构造函数而且需要函数重载,并且加入super(contex)等样式如下

我第一次做自定义view时就忘了使用super(context,attrs)这个方法,结果findviewbyid()找不到xml里面的控件

    public MyView(Context context) {
        super(context);//这个必须有否则findviewbyid找不到
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context,attrs);//这个必须有否则findviewbyid找不到
        init(context,attrs);
    }

二、必须重写 onDraw(Canvas canvas)方法

onDraw方法如下,使用postInvalidate()重新调用(onDraw)
@Override
protected void onDraw(Canvas canvas) {
}
我理解onDraw的解释:就是在这里画的意思。“在这里画”是一个简单的阐述:那么“这里”指的是哪里呢?用什么来画?怎么画才能不超过边框限制?我能不能自己制定画布尺寸?知道怎么画了一幅到底画到屏幕哪里了呢?下面一个一个的解释一下

1.“在这里画”的“这里”指的是:X轴:从0到getMeasuredWidth()(获取窗口宽度)结束。Y轴:从0到getMeasuredHeight()(获取窗口的高度)结束

3、用什么来画:用画笔画到画布上,其中画笔是:Paint 类。画布:Canvas类。画布可以无限大,但是view是有限的。

2、怎么画才能显示到边框内:上面介绍了窗口和画布的关系 ,其中窗口的尺寸是(上面已经介绍了):getMeasuredWidth()(获取窗口宽度)和getMeasuredHeight()(获取窗口的高度),所以是一个有限的大小(普通屏幕分辨率1920*1080)。而画布的大小我们可以随意设置,类型还是folat,设置几个亿也不会报错。所以如果一个画布尺寸和一个view尺寸如果设置的不对则不能正确显示。打个比喻,view就相当于望远镜,Canvas就相当于景色,景色很大但是望远镜只能看到其中一点

3、我们能不能自己定制画布尺寸:可以自定义画布的尺寸,使用setMeasuredDimension(宽,高)这个方法来设定画布的尺,单纯使用这个方法则不受父窗
控制,如果想让自定义view达到理想的尺寸进行绘制则需要重写onMeasure方法(下面介绍)

4、知道怎么画了一幅到底画到屏幕哪里了:可以通过下面四个方法获取

      	getLeft();//窗口左边到屏幕左边的距离
        getRight();//窗口右边到屏幕左边的距离
        getBottom();//窗口底边到顶的距离
        getTop();//窗口定编到屏幕顶的距离

三、重写onMeasure来确定view的尺寸

onMeasure方法的作用:打个比方客户需要种香蕉(xml设置) ,然后让管家(父窗口)分给你(自定义view)一块地去种香蕉,管家会先顾全大局分配了一块地给你(这个就是onMeasure方法),如果你看了一下这块地不够你种,你不用商量可以直接给管家闹翻,设置你需要的地方来种香蕉.
综合上述:
1、xml设置的 android:layout_width="##dp" 和android:layout_height="##dp"会使用 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)这个方法进行传递,其中widthMeasureSpec和heightMeasureSpec就是窗口的宽度和高度,但是,这个数值不能直接使用因为为了节省空间android把模式也压缩到了这个整数里面了,所以我们需要使用 int size=MeasureSpec.getSize(measureSpec))这个方法提取尺寸和int mode=MeasureSpec.getMode(measureSpec)这个方法提取父窗口给定的模式

2、这时候我们知道了模式和窗口的尺寸 只需要判断这个尺寸够不够,如果够我们用就是用父窗口传来的尺寸进行设置 否则无视父窗口给的尺寸直接设定自己想要的尺寸。设置尺寸使用setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),MeasureSpec.getSize(heightMeasureSpec));//设置父窗口给的尺寸
这段代码描述了onMeasure(),设置完窗口尺寸了就可以在onDraw

    private int getMySize(int defaultSize,int measureSpec){
        int mySize=defaultSize;
        int mode=MeasureSpec.getMode(measureSpec);//取测量模式
        int size=MeasureSpec.getSize(measureSpec);//取测量长度
        switch (mode){
            case MeasureSpec.UNSPECIFIED://如果没有指定大小,就设置为默认大小
                mySize=defaultSize;
                break;
            //如果测量模式是最大取值size
            //我们将大小取最大值,你也可以取其他值
            case MeasureSpec.AT_MOST:
                mySize=size;
                break;
            //如果是固定的大小,那就不要去改变它
            case MeasureSpec.EXACTLY:
                mySize=size;
                break;
        }
        return mySize;
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width=getMySize(100,widthMeasureSpec);
        int heigth=getMySize(100,heightMeasureSpec);
        if (width<heigth){
            heigth=width;
        }else{
            width=heigth;
        }
        setMeasuredDimension(width,heigth);
    }

四、一些绘制方法

    canvas.drawPoint(200, 200, paint);//画一个点

    canvas.drawLine(200, 300, 600, 300, paint);//画一条线
    canvas.drawLines(new float[]{200, 550, 350, 850, 200, 550, 600, 850},paint);//画多条线
    //画矩形
    //paint.setStyle(Paint.Style.FILL);这里设置的填充,如果想画空心的设置style为STROKE
    canvas.drawRect(100, 200, 300, 400, paint); //矩形第一种
    Rect rect = new Rect(100, 200, 300, 400);    //矩形第二种    
    canvas.drawRect(rect,paint);


    //画圆角矩形
    canvas.drawRoundRect(100, 200, 800, 600, 80, 80, paint);//第一种
    RectF rectF = new RectF(100, 200, 800, 600); //第二种
    canvas.drawRoundRect(rectF, 80, 80, paint); //第二种

	 //画椭圆
    canvas.drawOval(100, 200, 900, 600, paint);//第一种
    RectF rectF = new RectF(100, 200, 900, 600);//第二种
    canvas.drawOval(rectF,paint);

	//画圆
    canvas.drawCircle(500, 500, 250, paint);//  前两个参数是圆心坐标,第三个参数是半径
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!