自定义View总结

来源:互联网 发布:mac怎么修改磁盘名称 编辑:程序博客网 时间:2024/06/05 02:24

一. 自定义ViewGroup
1.. 自定义ViewGroup必须重写onMeasure(int widthMeasureSpec, int heightMeasureSpec):
a). 这是因为ViewGroup是abstract的,每个viewGroup都有自己的布局方式,因此无法像view一样给出统一的实现方式;
b). 另外,必须实现,是因为只有实现了此方法,其parentView才能根据其测量值来对他layout;
c). 实现方式是,利用ViewGroup提供的getChildCount(), getChildAt(), MeasureChildren得到所有child的测量值,然后根据child的getMeasuredWidth(), getMeasuredHeight()来根据自己的布局逻辑得到自身的测量值.
d). 得到测量值后的范围一般要在Parent给传进来的MeasureSpec范围内, 即parent告诉你我就给你这么点空间,你看着办,只能少,不能多。
e). 测量完毕后必须调用setMeasuredDimension()方法,否则无法通知Parent自己的测量值是多少。

2.. 重点是重写onLayout(changed, l, t, r, b)方法, 即为其每一个chlid摆放在正确的位置上!
a). 参数l, t, r, b都是都是Parent传进来的,表示ViewGroup自身的的左上角为在Parent中的相对位置。
b). 这个方法目的是为了把其每一个子child放置在此坐标系的哪个位置上,最终都是为了调用child.layout(l, t, r, b)!
c). 当然也利用了ViewGroup提供的方法来实现,同1-c).

二. 自定义View
1. onMeasure(),对于view来说需要关注AT_MOST的mode情况的处理。
2. onLayout(),对于view来说不存在,也无需再管。
3. onDraw(), 是view的重点,主要是对canvas的操作,必须熟悉。

上面均需要了解自定义view的xml,style, attrs的一些细节,以及对于margin, padding的一些处理,这里不做表述!

另外有一些其他需要注意的:
1. getMeasuredWidth()获取的是view原始的大小,也就是这个view在XML文件中配置或者是代码中设置的大小。getWidth()获取的是这个view最终显示的大小,这个大小有可能等于原始的大小也有可能不等于原始大小。
2. View的生命周期是 createView->onInflateFinished()->onAttachToWindow()->onMeasure->onSizeChanged->onLayout->onDraw->onDetachFromWindow.
3. canvas save 的是 canvas当时的大小,角度,坐标系(clip不会改变坐标系), restore会把栈顶的状态pop出来,然后每次canvas.drawXX时都是产生一个全新的画布(即上面什么都没有,canvas状态和目前restore出来的一样,包括裁剪的大小,坐标系,角度),然后在上面画,画完贴到window上,和原有画的图复合。

事件传递机制:
View
dispatchTouchEvent : YES
onInterceptTouchEvent:NO
onTouchEvent:YES (一般return false)

ViewGroup
dispatchTouchEvent : YES
onInterceptTouchEvent:return false
onTouchEvent:继承View

YES表示有自己的实现方法,NO表示没有此方法,由此可见ViewGroup默认是不拦截事件的,当你自定义的ViewGroup需要拦截此事件时,那么你需要override此方法,然后再override onTouchEvent里实现你自己想要的效果。

// dispatchTouchEvent本身的返回值表示此ViewGroup所代表的区域是否要消耗此事件,如果true,则此后续的事件序列也会传给它;否则后续事件不会再传给它;public boolean dispatchTouchEvent(){    // 先看自己是否能消耗此事件,则后续事件序列会给它自身    if(onInterceptTouchEvent() && onTouchEvent())        return true;    else // 否则,看看其子view是否有能消耗此事件        return child.dispatchTouchEvent();}

注意如果只是想点击一下的效果,可以直接调用performClick()。

原创粉丝点击