美文网首页
自定义View系列(一)生命周期简介

自定义View系列(一)生命周期简介

作者: Ayres | 来源:发表于2017-07-12 10:15 被阅读0次

一、概述

自定义View对很多人来说都比较畏惧,认为它比较难,关键还是缺少实践。当你写的多了,见得多了,也就习以为常了,关键是勇敢去尝试。在开发中,我们刚开始很多时候是,公司设计了一种效果,我们立马,去github或者百度再或者其他网站找相同效果,特别是在github上,找到之后直接添加依赖,看一下怎么使用,就完成效果实现。但当我们工作几年之后,还处于找别人添加依赖,对源码不懂,不会自定义,那么无疑会早晚被淘汰。所以今天,个人回顾一下同时写点笔记,对自己也是加强巩固,同时也希望对别人有所帮助。

二、生命周期

清楚的了解View的生命周期,才能更好的自定义view。生命周期包括:

1.创建对象

有两种方式:一直接new,另外一种通过xml布局文件,同时他们所走的方法也有所不同

    /**
     * new的方式走该方法
     * @param context
     */
    public Textview(Context context) {
        super(context);
    }

    /**
     * xml文件中走该方法
     * @param context
     * @param attrs
     */
    public Textview(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * xml文件 有style时走该方法
     * @param context
     * @param attrs
     * @param defStyleAttr
     */
    public Textview(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

onFinishInflate() 方法只有布局创建对象方式才会调用,重写的目的是可以得到子View,利用getChildAt(int index)获得子view对象,index是指按照加载顺序排列。
onAttachedToWindow()方法也是创建对象时可以重写的方法,目的也是可以得到字view

2.测量:onMeasure()方法

测量离不开测量模式的介绍,当然测量模式也与父view有关 ,暂时不做解释,测量模式分别是UNSPECIFIED,EXACTLY,AT_MOST。
源码解释为

     /**
     * Measure specification mode: The parent has not imposed any constraint
     * on the child. It can be whatever size it wants.
     */
    public static final int UNSPECIFIED = 0 << MODE_SHIFT;

    /**
     * Measure specification mode: The parent has determined an exact size
     * for the child. The child is going to be given those bounds regardless
     * of how big it wants to be.
     */
    public static final int EXACTLY     = 1 << MODE_SHIFT;

    /**
     * Measure specification mode: The child can be as large as it wants up
     * to the specified size.
     */
    public static final int AT_MOST     = 2 << MODE_SHIFT;

UNSPECIFIED :表示任意大小,一般我们不会遇到,如ListView,RecyclerView,ScrollView测量子View的时候给的就是UNSPECIFIED ,一般开发中不需要关注它;
EXACTLY :表示一个确定的值,比如在布局中你是这样写的layout_width="100dp","match_parent","fill_parent";
AT_MOST:包裹内容,比如在布局中你是这样写的layout_width="wrap_content"。

另外当mearure()中计算出的视图的宽高就会调用此方法, 在此方法默认保存的视图测量的宽高
注意:视图测量的宽高不等同于视图的宽高。获取的时机不同,重写的意义:得到当前视图/子视图测量的宽高;保存我们自己指定的宽高。mearure()方法不能够被重写。

3.布局:onLayout()方法

在layout()的过程中, 如果某视图的位置改变或强制重新布局就会调用此方法,重写它的意义可以对子View进行重新布局,view.requestLayout() 是强制重新布局的方法。

4.绘制: onDraw()方法

主要用来绘制效果,里面会有一个参数那就是canvas画布,利用canvas就可以画各式各样的效果,如:canvas.drawCircle()画圆形,canvas.drawBitmap()画bitmap,我们这里肯定是需要画文字,那就是drawText()画文本。

      @Override
       protected void onDraw(Canvas canvas) {
               // 画圆
           canvas.drawCircle();
               // 画bitmap
           canvas.drawBitmap();
              // 画文本
           canvas.drawText();
          // ......
        }

强制重绘的两个方法
invalidate() :只能在主线程执行
postInvalidate() :可以在主线程或分线程执行

5.事件处理:onTouch()方法

用来处理触摸事件与用户进行交互,MotionEvent.ACTION_DOWN(手指按下)、MotionEvent.ACTION_MOVE(手指移动)、ACTION_UP(手指抬起)。

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.e(TAG,"ACTION_DOWN");
            break;
        case MotionEvent.ACTION_MOVE:
            Log.e(TAG,"ACTION_MOVE");
            break;
        case MotionEvent.ACTION_UP:
            Log.e(TAG,"ACTION_UP");
            break;
    }
    return super.onTouchEvent(event);
}

当然还有一个比较难以处理的,就是事件分发问题,要看过源码才行。


Paste_Image.png
6.死亡:onDetachedFromWindow()方法

Activity死亡之前,视图对象被移除。

相关文章

网友评论

      本文标题:自定义View系列(一)生命周期简介

      本文链接:https://www.haomeiwen.com/subject/vzgvhxtx.html