概述
安卓开发进阶的必经之路
为什么要自定义视图
自定义视图的基本方法
自定义查看的最基本的三个方法分别是:onMeasure(),onLayout(),onDraw(); 查看在活动中显示出来,要经历测量,布局和绘制三个步骤,分别对应三个动作:测量,布局和平局。
-
测量:onMeasure()决定查看的大小;
-
布局:onLayout()决定查看在一个ViewGroup中的位置;
-
绘制:的onDraw()决定绘制这个视图。
自定义控件分类
-
自定义查看:只需要重写onMeasure()和onDraw()
-
自定义ViewGroup:则只需要重写onMeasure()和onLayout()
自定义视图基础
查看的分类
视图查看主要分为两类
类别 | 解释 | 特点 |
---|---|---|
单一视图 | 即一个视图,如TextView的 | 不包含子视图 |
视图组 | 即多个视图组成的ViewGroup中,如的LinearLayout | 包含子视图 |
查看类简介
-
查看类是Android的中各种组件的基类,如视图是一个ViewGroup基类
-
查看表现为显示在屏幕上的各种视图
安卓中的UI组件都由查看,ViewGroup中组成。
-
查看的构造函数:共有4个
//如果查看是在Java代码里面new的,则调用第一个构造函数public CarsonView(Context context){ super(context); } //如果视图是在.XML里声明的,则调用第二个构造函数//自定义属性是从AttributeSet中参数传进来的公共CarsonView(语境上下文,AttributeSet中ATTRS){ 超级(上下文,ATTRS); } //不会自动调用//一般是在第二个构造函数里主动调用//如查看有风格属性时公开CarsonView(上下文语境, AttributeSet attrs,int defStyleAttr){ super(context,attrs,defStyleAttr); } // API21之后才使用//不会自动调用//一般是在第二个构造函数里主动调用//如查看有风格属性时公开CarsonView(上下文语境,AttributeSet中的ATTRS,INT defStyleAttr,INT defStyleRes) { super(context,attrs,defStyleAttr,defStyleRes); }
public CarsonView(Context context){ super(context); } //如果视图是在.XML里声明的,则调用第二个构造函数//自定义属性是从AttributeSet中参数传进来的公共CarsonView(语境上下文,AttributeSet中ATTRS){ 超级(上下文,ATTRS); } //不会自动调用//一般是在第二个构造函数里主动调用//如查看有风格属性时公开CarsonView(上下文语境, AttributeSet attrs,int defStyleAttr){ super(context,attrs,defStyleAttr); } // API21之后才使用//不会自动调用//一般是在第二个构造函数里主动调用//如查看有风格属性时公开CarsonView(上下文语境,AttributeSet中的ATTRS,INT defStyleAttr,INT defStyleRes) { super(context,attrs,defStyleAttr,defStyleRes); }
AttributeSet中的与自定义属性
系统自带的浏览可以在XML中配置属性,对于写的好的自定义视图同样可以在XML中配置属性,为了使自定义的视图的属性可以在XML中配置,需要以下4个步骤:
-
通过为自定义视图添加属性
<declare-styleable>
-
在XML中为相应的属性声明属性值
-
在运行时(一般为构造函数)获取属性值
-
将获取到的属性值应用到景观
查看视图结构
-
PhoneWindow是Android的系统中最基本的窗口系统,继承自视窗类,负责管理界面显示以及事件响应。它是活动与景观系统交互的接口
-
DecorView是PhoneWindow中的起始节点观,继承于视图类,作为整个视图容器来使用。用于设置窗口属性。它本质上是一个的FrameLayout
-
的ViewRoot在Activtiy启动时创建,负责管理,布局,渲染窗口UI等等
对于多视图的视图,结构是树形结构:最顶层是一个ViewGroup的ViewGroup以及下可能有多个ViewGroup中或查看,如下图:
一定要记住:无论是测量过程,布局过程还是绘制过程,永远都是从搜索树的根节点开始测量或计算(即从树的顶端开始),一层一层,一个分支一个分支地进行(即树形递归),最终计算整个景观树中各个视图,最终确定整个景观树的相关属性。
Android的坐标系
安卓的坐标系定义为:
-
屏幕的左上角为坐标原点
-
向右为X轴增大方向
-
向下为ÿ轴增大方向
区别于一般的数学坐标系
查看位置(坐标)描述
查看的位置由4个顶点决定的4个顶点的位置描述分别由4个值决定:
请记住:查看的位置是相对于父控件而言的)
-
上图:子视图上边界到父视图上边界的距离
-
左:子视图左边界到父视图左边界的距离
-
下图:子视图下边距到父视图上边界的距离
-
右:子查看右边界到父视图左边界的距离
位置获取方式
查看的位置是通过view.getxxx()函数进行获取:(以最为例)
public final int getTop(){ return mTop ; } //其余如下:getLeft(); //获取子查看左上角距父查看左侧的距离getBottom(); //获取子查看右下角距父查看顶部的距离getRight(); //获取子视图右下角距父视图左侧的距离
与MotionEvent中get()和getRaw()的区别
// get():触摸点相对于其所所组件坐标系的坐标事件。getX(); 事件。的getY(); // getRaw():触摸点相对于屏幕默认坐标系的坐标事件。getRawX(); 事件。getRawY();
事件。getX(); 事件。的getY(); // getRaw():触摸点相对于屏幕默认坐标系的坐标事件。getRawX(); 事件。getRawY();
安卓中颜色相关内容
Android的支持的颜色模式:以ARGB8888为例介绍颜色定义:
查看树的绘制流程
查看树的绘制流程是谁负责的?
视图树的绘制流程是通过的ViewRoot去负责绘制的,的ViewRoot这个类的命名有点坑,最初看到这个名字,翻译过来是视图的根节点,但是事实完全不是这样,的ViewRoot其实不是查看的根节点,它连视图节点都算不上,它的主要作用是查看树的管理者,负责将DecorView和PhoneWindow“组合”起来,而查看树的根节点严格意义上来说只有DecorView;每个DecorView都有一个的ViewRoot与之关联,这种关联关系是由窗口管理去进行管理的;
观点的添加
查看的绘制流程
测量
-
系统为什么要有措施过程?
-
测量过程都干了点什么事?
-
对于自适应的尺寸机制,如何合理的测量一颗景观树?
-
那么ViewGroup中是如何向子查看传递限制信息的?
-
滚动型嵌套的ListView问题?
布局
-
系统为什么要有布局过程?
-
布局过程都干了点什么事?
画
-
系统为什么要有画过程?
-
绘制过程都干了点什么事?
的LayoutParams
ayoutParams翻译过来就是布局参数,子视图通过的LayoutParams告诉父容器(ViewGroup中)应该如何放置自己。从这个定义中也可以看出来的LayoutParams与ViewGroup中是息息相关的,因此脱离的ViewGroup谈的LayoutParams是没有意义的。
事实上,每个的ViewGroup的子类都有自己对应的的LayoutParams类,典型的如LinearLayout.LayoutParams和FrameLayout.LayoutParams等,可以看出来的LayoutParams都是对应的ViewGroup子类的内部类
MarginLayoutParams
MarginLayoutParams是和外间距有关的。事实也确实如此,和的LayoutParams相比,MarginLayoutParams只是增加了对上下左右外间距的支持。实际上大部分的LayoutParams的实现类都是继承自MarginLayoutParams,因为基本所有的父容器都是支持子视图设置外间距的
-
属性优先级问题MarginLayoutParams主要就是增加了上下左右4种外间距在构造方法中,先是获取了余量属性;如果该值不合法,就获取horizontalMargin;如果该值不合法,再去获取LEFTMARGIN和rightMargin属性(verti