Android 控件架构
Android View 视图 可以理解为一棵树,这个树有主干,有分支,有树叶,我们把ViewParent可以理解为树的主干,把ViewGroup理解为分支,每一个分支上可能都会有树叶,而树叶就是View。
通常在Activity当中,我们使用findViewById()方法,以树的深度优先遍历来查找视图树里的元素,
View视图树如下所示(绘图工具使用的是ProcessOn,挺好的一个在线绘图工具)
UI界面架构图
界面的全屏显示
requestWindowFeature(Window.FEATURE_NO_TITLE)来设置全屏显示,这个方法的调用一定要在setContentView()前。
界面的绘制
当程序在onCreate()方法中调用setContentView()方法后,ActivityManageService会回调onResume()方法,此时系统才会把整个DecorView添加到PhoneWindow中。
View的测量
View的测量在onMeasure()方法里重写,通过MeasureSpec类,测量的模式分为EXACTLY(固定宽度,默认是),AT_MOST(最大),UNSPECFIED(不指定)。
onMeasure()的super.measure(width,height)源码实现会调用setMeasureDimension(),我们把自定义的宽高传给它,就可以实现View大小的自定义了。
自定义宽高的模板方法:height与width类似
private int measureWidth(int measureSpec){
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if(specMode = MeasureSpec.EXACTLY){
result = specSize;
}else{
result = 200;
if(specMode = MeasureSpec.AT_MOST)
result = Math.min(result,specSize);
}
return result;
}
View的绘制
View的绘制我们可以用onDraw()来重写实现,两个重要的参数,Canvas画布,Paint 画笔
自定义View的绘制没有什么难点,主要是调用API函数,具体学习可以参考-自定义View大佬朱凯的扔物线_给高级Android工程师的进阶手册
事件拦截机制分析
事件冲突的造成的原因:多层ViewGroup,View嵌套
Android里的事件传递,处理,通过MotionEvent这一关键类,重写onTouchEvent()方法。
在MotionEvent这个类里,
有获取触摸点的坐标,可以通过event.getX()方法---基于组件左上角和event.getRawX()方法---基于屏幕左上角。
有点击事件的Action,MotionEvent.ACTION_DOWN(手指按下),MotionEvent.ACTION_MOVE(手指移动),MotionEvent.ACTION_UP(手指抬起)。
注意:自定义ViewGroup的时候,务必重写onLayout()方法,不然子View是不会显示的。
当点击红色的View时,事件传递如图:
当点击黄色的View时,事件传递如图所示:
不知道小伙伴有没有发现规律,点击外层黑色View应该是……,很简单,尝试着做一做,这个留给读者思考吧~
总之,事件传递由外层到内层,事件处理由内层到外层。
事件传递的返回值也很容易,True:拦截 False:不拦截
事件处理的返回值类似:True:处理,False:不处理
初始情况下,两种返回值都是 False