Android自定义View(1)
首先我们首先要了解什么是View。
官方文档是这么写的:
This class represents the basic building block for user interface components. A View occupies a rectangular area on the screen and is responsible for drawing and event handling. View is the base class for widgets, which are used to create interactive UI components (buttons, text fields, etc.). The ViewGroup subclass is the base class for layouts, which are invisible containers that hold other Views (or other ViewGroups) and define their layout properties.
View是最基本的UI类,基本上所有的高级UI组件都是继承View类实现,如TextView(文本框)、Button(按钮)、List(列表)、EditText(编辑框)、RadioButton、Checkbox 等。一个View在屏幕着占据一块矩形区域,它负责渲染这块矩形区域,也处理这块矩形区域发生的事件,并可以设置该区域是否可见以及获取焦点等。
ViwGroup:View的子类,所以它也具有View的特性,但它主要用来充当View的容器,将其中的View视作自己的孩子,对它的子View进行管理,当然它的孩子也可以是ViewGroup类型。
1、确定每个View的位置
我们在活动中调用了setContentView(View),实际上就是将用户界面的所有的View交给了DecorView(一个超级复合View,用它来包含住所有的其他View)中的一个FrameLayout,这个FrameLayou代表着可以分配给用户界面使用的屏幕区域。大多数情况下,我们的界面都是由五大布局组成的,里面包含着其他的ViewGroup和View。首先这个ViewGroup(布局)就会占据上面所指的FrameLayout所代表的屏幕区域,剩下的任务,就是这个ViewGroup给它内部的小弟们(各种ViewGroup和各种View)分配区域了。至于怎么分,不同的ViewGroup有不同的分法。我们可以通过各种配置来设置View在Viewgroup的位置。
2.确定View的大小
确定View的大小,是一个开发者,View,ViewGroup三方商量的过程。
第一步:
开发者在写布局文件的时候,会为一个View填上android:layout_width= android:layout_height= 两个配置,这是开发者向ViewGroup表达的,我这个View需要的大小是多少。星号的取值有三种:
1.具体值,如50dp
2.match_parent ,表示开发者向ViewGroup说,把你所有的屏幕区域都给这个View吧。
3.wrap_parent,表示开发者向ViewGroup说,只要给这个View够他展示自己的空间就行,至于到底给多少,你直接跟View沟通吧,看它怎么说。
第二步:
ViewGroup收到了开发者对View大小的说明,然后ViewGroup会综合考虑自己的空间和开发者的请求,然后生成两个MeasureSpec对象(width与height)传给View,这两个对象是ViewGroup向子View提出的要求,就相当于告诉子View:“我已经与开发者商量过了,现在把我们商量确定的结果告诉你,你的宽度不能违反width MeasureSpec对象的要求,你的高度不能违反height MeasureSpec对象的要求,现在,你赶紧根据这个要求确定下自己要多大空间,只许少,不许多“。
然后这两个MeasureSpec对象会传给View的onMeasure方法中,子View根据传入的MeasureSpec对象解译出如下信息
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
Mode和Size一起准确无误的表达ViewGroup的要求。
Mode的取值有三种:
- EXACTLY(精确模式),ViewGroup对View强制要求大小,是多少就是多少。
- AT_MOST(最大模式),ViewGroup给View最大的大小,开发者让这个组件占据wrap_content的大小(刚好显示这个组件),但是每个组件显示的内容不一,大小也不一,所以无法确定,这时候ViewGroup就会给View一个最大值,“我不知道你要占多少空间,但是最多你只能占那么多”。
UNSPECIFIED(无限制),当前组件,可以随便用空间,不受限制。
第三步:
告诉ViewGroup自己确定的大小,安排位置。