您的位置:首页 > 其它

个人进阶之路——自定义控件(6)

2016-02-28 00:56 218 查看
Layout过程

Layout 作用:ViewGroup用来确定子元素的位置

位置确定后,在onLayout中遍历所有的子元素,调用其layout方法,在layout方法中onLayout方法又会被调用

Layout方法确定View本身的位置

onLayout方法确定所有子元素的位置

layout方法的大概流程:通过setFrame来设定View的四个顶点的位置,初始化mLeft等四个值。

View的是个顶点确定后,View在父容器中的位置确定,调用onLayout方法,父容器确定子元素的位置

onLayout的布局与具体的布局有关

View和ViewGroup均没有真正实现onLayout方法

将一下LinearLayout中的onLayout方法,其中的layoutVertical会遍历所有子元素并且调用setChildFrame,仅仅是调用子元素的Layout方法而已,完成layout定位后,通过onlayout方法去调用子元素的layout方法,子元素又会通过自己的layout方法来确定自己的位置,这样逐层传递,完成view树的layout。

SetChildFrame的width和height实际上是子元素的测量宽高

layout方法中会通过setFrame去设置子元素的四个顶点位置

View的测量宽高和最终宽高有什么区别?

View的getMeasuredWidth和getWidth方法有什么区别?

getWidth方法返回值刚好是View的测量宽度

在View的默认实现中,View的测量宽高和最终宽高是相等的

测量宽高形成于View的Measure过程

最终宽高形成于View的layout过程

两者的赋值时机不同,测量宽高的赋值时机会稍微早一点

日常开发中,可以认为View的测量宽高等于最终宽高,但是的确存在某些特殊情况会导致两者不一样

view需要多次measure才能确定自己的测量宽高

在前几次的测量过程中,其得出的侧量宽高有可能和最终宽高不一致,但是最终来说,测量宽高还是和最终宽高相同

draw过程

作用:将View绘制到屏幕上面

(1)绘制背景background.draw(canvas)

(2)绘制自己(onDraw)

(3)绘制children(dispatchDraw)

(4)绘制装饰(onDrawScrollBars)

View 的绘制过程的传递时通过dispatchDraw来实现的,通过遍历所有子元素的draw方法,如此draw事件就逐层的传递下去

setWillNotDraw,如果一个View不需要绘制任何内容,那么设置这个标记位为true后,系统会进行相应优化。

默认情况下,View没有启用这个优化标记位,但是ViewGroup会默认启动这个标记位

开发的实际 意义是:自定义控件继承于ViewGroup,并且本身不具备绘制功能时,可开该标记位,便于系统进行后续的优化

当明确知道一个ViewGroup需要通过onDraw来绘制内容时,需要显示地关闭WILL_NOT_DRAW标记位

自定义View分类

1、继承View 重写onDraw方法

实现一些不规则的效果,该效果不方便通过布局的组合方式来达到

往往需要静态或动态显示一些不规则的图形

需要通过绘制的方式来实现,重写onDraw方法

采用该方式,需要自己支持wrap_content,并且padding也需要自己处理

2、继承ViewGroup派生特殊的Layout

主要用于实现自定义的布局,除了系统的布局外,重新定义的一种新布局

该方式稍微复杂些,需要合适地处理ViewGroup的测量,布局这两个过程,并同时处理子元素的测量和布局过程

3、继承特定的View(TextView)

方法比较常见,用于扩展某种已有的view的功能,比较容易实现,不需要自己支持wrap_content和padding

4、继承特定的ViewGroup(LinearLayout)

方法比较常见,当某种效果看起来很像几种View组合在一起的时候,可以采用这种方式实现,

采用该方法不需要自己处理ViewGroup的测量和布局。

注意和方法2的区别,一般来说,方法2能实现的效果4也都能实现。两者的区别是,方法2更接近于View底层

自定义View过程中常见的注意事项

1、让View支持wrap_content

直接继承View或者ViewGroup的控件,如果不在onMeasure中对wrap_content做特殊处理,那么当外界在布局中使用wrap_content时就无法达到预期的效果

2、如果有必要,让你的view支持padding

直接继承view的控件,如果不在draw方法中处理padding,那么padding属性是无法起作用的。

直接继承自ViewGroup的控件需要在onMeasure和onLayout中考虑padding和子元素的margin对其造成的影响,不然将导致padding和子元素的margin失效

3、尽量不要在View中使用Handler,没有必要

View内部本身就提供post系列的方法,完全可以替代Handler的作用,除非明确要使用handler来发送消息

4、View中如果有线程或者动画,需要及时停止,参考View#onDetachedFromWindow

如果有线程或者动画需要停止时,onDetachedFromWindow是一个好时机,

当包含此View的Activity退出或者当前View被remove时,View的onDetachedFromWindow方法被调用,

对应于onAttachedToWindow,当包含此View的Activity启动时,View的onAttachedToWindow方法会被调用。

同时,当View变得不可见时,需要停止线程和动画,如果不及时处理这种问题,有可能会造成内存泄露。

5、View带有滑动嵌套情形时,需要处理好滑动冲突

如果有滑动冲突的话,适合地处理滑动冲突,否则将会严重影响View的效果
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: