笔记·Android控件架构与自定义控件详解
Posted xiang_freedom
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了笔记·Android控件架构与自定义控件详解相关的知识,希望对你有一定的参考价值。
android控件架构
- Android中,控件大致被分为两类,即ViewGroup控件与View控件。ViewGroup控件作为父控件可以包含多个View控件,并管理其包含的View控件。
通常在Activity中使用的findViewById()方法,就是在控件树中以树的深度优先遍历来查找对应元素。
View树结构:
UI界面架构图:
- PhoneWindow将一个DecorView设置为整个应用窗口的根View。
DecorView将要显示的具体内容呈现在了PhoneWindow上,这里面的所有View的监听事件,都通过WindowManagerService来进行接收,并通过Activity对象来回调相应的onClickLisener。
- 在代码中,程序在onCreate方法调用setContentView方法后,ActivityManagerService会回调onResume方法,此时系统才会把整个DecorView添加到PhoneWindow中,并让其显示出来,从而完成界面的绘制。
View的测量
- Android在绘制View前,也必须对View进行测量,即告诉系统该画一个多大的View。这个过程在onMeasure方法中进行。
Android给我们提供了一个设计短小精悍却功能强大的类——MeasureSpec类,通过它来帮助我们测量View。MeasureSpec是一个32位的int值,其中高2位为测量的模式,低30位为测量的大小,在计算中使用位运算的原因是为了提高并优化效率。
- onMeasure方法:父控件传递给子控件的“建议”尺寸大小,两个参数表示宽高大小及测量模式(MeasureSpec类介绍及使用详解)。如果是ViewGroup,且大小为Wrap_content时,则需要遍历所有子View测量他们的大小,然后设置自身的大小。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
setMeasureDimension方法:将测量后的尺寸传递给子控件,完成测量工作。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
setMeasureDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec));
public static int measureWidth(int measureSpec) //根据父控件给的建议尺寸和测量模式,计算相应的尺寸 int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) case MeasureSpec.UNSPECIFIED: result = size; break; case MeasureSpec.AT_MOST: result = 200;//指定view的大小 result = Math.min(result, specSize); break; case MeasureSpec.EXACTLY: result = specSize; break; return result;
ViewGroup的子View位置设定
在ViewGrope及其子View完成测量之后,需要对子view进行放置位置的设定。在放置子view前,需要确定整个vewGroup的高度。然后在OnLayout方法中遍历调用子view的layout方法设定具体位置。
View的绘制
- 过程:重写onDraw(),在Canvas对象上绘制图形。Canvas为系统2D绘图API必须要使用的对象。
- canvas通常会带有一个bitmap参数,用于存储绘制在canvas上的像素信息。当创建了含有bitmap的canvas对象后,所有canvas.drawxxx方法都发生在这个bitmap上。值得注意的是,view的onDraw方法中会创建两个bitmap,并将第二个bitmap封装到另一个canvas对象中,只在第二个bitmap上进行绘图。
- ViewGroup的绘制:如果没有设置背景色,不会调用onDraw方法,而是调用dispatchDraw方法绘制子View。原理也是遍历子view并调用其绘制方法。
自定义View
- 自定义View通常需要重写onDraw方法来绘制自定义内容。如果设置了wrap_content属性,那么必须重写onMeasure方法测量大小。
- View中有一些重要的回调方法:
- onFinishInflate():从XML加载组件后回调
- onSizeChanged():组件大小改变时回调
- onMeasure:测量
- onLayout():回调该方法来确定显示的位置
- onTouchEvent():监听到触摸事件回调
实现自定义控件的方式
事件拦截机制
- 几个重要的方法:dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent.
- 从ViewGroup到view的事件分发和处理回调事件顺序如下(以ViewGroupA,ViewGroupB,view为例):
ViewGroupA.dispatchTouchEvent –> ViewGroupA.onInterceptTouchEvent –> ViewGroupB.dispatchTouchEvent –> ViewGroupB.onInterceptTouchEvent –> view.dispatchTouchEvent –> view.onTouchEvent –> ViewGroupB.onTouchEvent –> ViewGroupA.onTouchEvent
解释:
- dispatchTouchEvent方法用于分发事件,一般不用重写。onInterceptTouchEvent用来拦截TouchEvent,onTouchEvent用来处理TouchEvent。
- onInterceptTouchEvent返回true则拦截事件,不往下分发;onTouchEvent返回true则不往上回调。
以上是关于笔记·Android控件架构与自定义控件详解的主要内容,如果未能解决你的问题,请参考以下文章