3.1.1 View与ViewGroup浅析

3.1.1 View与ViewGroup浅析

标签: StudyNote

本文声明
本文由Coder-pig编写,想了解其他内容,可见CoderPig’s Android Study Note——目录
尊重作者劳动成果,未经本人授权,禁止转载!违者必究!
目录源地址:http://blog.csdn.net/coder_pig/article/details/51348769

1.简单介绍

  在Android APP中,所有的用户界面元素都是由ViewViewGroup的对象
构成的。View是绘制在屏幕上的,用户能与之交互的一个对象。而ViewGroup
则是一个用于存放其他View(和ViewGroup)对象的布局容器!
(ViewGroup是View的子类!)

  每个界面都是由View和ViewGroup组成的层次树(树形结构),我们可以根据
自己的需求,设计简单或者复杂的布局(PS:布局越简单性能越好,避免过多的布局嵌套)。

3.1.1 View与ViewGroup浅析_第1张图片

最顶层的ViewGroup我们有时也把他称为ViewParent对象,所有的交互管理事件都由
他来统一调度分配。而在Android中我们一般都是在Activity上创建用户界面,除此之外
Activity提供一些事件处理以及生命周期相关的API,Activity并不做和绘制有关的事情,
你更多的时候可以把他看作一个界面载体,在Activity中有一个Window抽象类
(通常由PhoneWindow实现)由他来完成绘制,当我们调用Activity的
setContentView()方法时,其实调用的就是Window的setContentView()方法。
而在Window类中有一个DecorView的内部类(FrameLayout扩展类),
在PhoneWindow调用setContentView()方法的时候会调用一个installDecor()的方法,
而在该方法中会创建一个DecorView作为整个应用窗口的根View。里面所有的View
的监听事件由WindowManagerService(WMS)来接收,通过Activity回调对应
的onClickListener。然后就到如图所示的TitleViewContentView了,
我们平时调用setContentView设置的就是ContentView这里的布局!

3.1.1 View与ViewGroup浅析_第2张图片

2.View的绘制流程简述

View树是遍历绘制的,每绘制一个View的逻辑是:

Created with Raphaël 2.1.0 View的绘制流程 是否需要重新测量视图大小(Measure) 是否需要重新布局(Layout) 是否重新需要绘制(Draw) View绘制完成

onMeasure(测量)

首先是测量(Measure) View的大小:
核心API是:MeasureSpec,int类型,32位,高2位保存SpecMode(测量模式),低30
位置为SpecSize(测量大小)。
测量模式有三种:

  • EXACTLY(大小固定):指定大小或者设置为match_parent会使用这个模式。
  • AT_MOST(最大值):指定为warp_content时会使用这个模式,控件大小随
    内容与子空间变化而变化,只要不超过父控件允许的最大尺寸即可。
  • UNSPECIFIED:不做任何限制,View想绘制多大就多大,自定义View才会用到。

View默认的onMeasure()方法只支持EXACTLY模式,在自定义View时不重写onMeasure()
方法就只能使用EXACTLY模式,即只支持具体大小与match_parent。如果想支持wrap_content
或者想支持UNSPECIFIED模式的话,需要重写onMeasure()方法,在onMeasure()方法中,有一个
setMeasuredDimension(measuredWidth,measureHeight)的方法,将测量后的宽高传入
即可完成测量工作,贴下简单的模板代码:

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec));
    }

    private int measureWidth(int widthMeasureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);

        switch (specMode) {
            case MeasureSpec.EXACTLY:
                result = specSize;
                break;
            case MeasureSpec.AT_MOST:
                result = Math.min(200,specSize);    
                break;
            case MeasureSpec.UNSPECIFIED:
                result = 300;
                break;
        }
        return result;
    }

onLayout(位置)

确定View的位置,但是要注意一点的是,一般是自定义ViewGroup才会来重写onLayout()
这个方法,ViewGroup会遍子View,然后调用该子View的layout()方法设置他的坐标值。

简单示例如下:

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        for (int i = 0, size = getChildCount(); i < size; i++) {
            View childView = getChildAt(i);

            // 获取在onMeasure中计算的视图尺寸
            int measureHeight = childView.getMeasuredHeight();
            int measuredWidth = childView.getMeasuredWidth();

            childView.layout(left,0,measuredWidth,measureHeight);
        }
    }

onDraw(绘制)

大小和位置都确定了,接着就是绘制了,onDraw()方法为我们提供了一个Canvas画板,
然后可以调用绘图相关的API对View进行绘制,我们可以在其它地方调用:
invalidate或者postInvalidate方法,让View进行重绘!

3.View与ViewGroup属性汇总

——摘自:宅学长的博客

第一类:属性值 true或者 false

属性 说明
android:layout_centerHrizontal 水平居中
android:layout_centerVertical 垂直居中
android:layout_centerInparent 相对于父元素完全居中
android:layout_alignParentBottom 贴紧父元素的下边缘
android:layout_alignParentLeft 贴紧父元素的左边缘
android:layout_alignParentRight 贴紧父元素的右边缘
android:layout_alignParentTop 贴紧父元素的上边缘
android:layout_alignWithParentIfMissing 如果对应的兄弟元素找不到的话就以父元素做参照物
android:layout_alignParentStart 紧贴父元素结束位置开始
android:layout_alignParentEnd 紧贴父元素结束位置结束
android:animateLayoutChanges 布局改变时是否有动画效果
android:clipChildren 定义子布局是否一定要在限定的区域内
android:clipToPadding 定义布局间是否有间距
android:animationCache 定义子布局也有动画效果
android:alwaysDrawnWithCache 定义子布局是否应用绘图的高速缓存
android:addStatesFromChildren 定义布局是否应用子布局的背景
android:splitMotionEvents 定义布局是否传递touch事件到子布局
android:focusableInTouchMode 定义是否可以通过touch获取到焦点
android:isScrollContainer 定义布局是否作为一个滚动容器 可以调整整个窗体
android:fadeScrollbars 滚动条自动隐藏
android:fitsSystemWindows 设置布局调整时是否考虑系统窗口(如状态栏)
android:visibility 定义布局是否可见
android:requiresFadingEdge 定义滚动时边缘是否褪色
android:clickable 定义是否可点击
android:longClickable 定义是否可长点击
android:saveEnabled 设置是否在窗口冻结时(如旋转屏幕)保存View的数据
android:filterTouchesWhenObscured 所在窗口被其它可见窗口遮住时,是否过滤触摸事件
android:keepScreenOn 设置屏幕常亮
android:duplicateParentState 是否从父容器中获取绘图状态(光标,按下等)
android:soundEffectsEnabled 点击或触摸是否有声音效果
android:hapticFeedbackEnabled 设置触感反馈

第二类:属性值必须为id的引用名“@id/idname”

属性 说明
android:layout_alignBaseline 本元素的文本与父元素文本对齐
android:layout_below 在某元素的下方
android:layout_above 在某元素的的上方
android:layout_toLeftOf 在某元素的左边
android:layout_toRightOf 在某元素的右边
android:layout_toStartOf 本元素从某个元素开始
android:layout_toEndOf 本元素在某个元素结束
android:layout_alignTop 本元素的上边缘和某元素的的上边缘对齐
android:layout_alignLeft 本元素的左边缘和某元素的的左边缘对齐
android:layout_alignBottom 本元素的下边缘和某元素的的下边缘对齐
android:layout_alignRight 本元素的右边缘和某元素的的右边缘对齐
android:layout_alignStart 本元素与开始的父元素对齐
android:layout_alignEnd 本元素与结束的父元素对齐
android:ignoreGravity 指定元素不受重力的影响
android:layoutAnimation 定义布局显示时候的动画
android:id 为布局添加ID方便查找
android:tag 为布局添加tag方便查找与类似
android:scrollbarThumbHorizontal 设置水平滚动条的drawable
android:scrollbarThumbVertical 设置垂直滚动条的drawable
android:scrollbarTrackHorizontal 设置水平滚动条背景(轨迹)的色drawable
android:scrollbarTrackVertical 设置垂直滚动条背景(轨迹)的色drawable
android:scrollbarAlwaysDrawHorizontalTrack 设置水平滚动条是否含有轨道
android:scrollbarAlwaysDrawVerticalTrack 设置垂直滚动条是否含有轨道
android:nextFocusLeft 设置左边指定视图获得下一个焦点
android:nextFocusRight 设置右边指定视图获得下一个焦点
android:nextFocusUp 设置上边指定视图获得下一个焦点
android:nextFocusDown 设置下边指定视图获得下一个焦点
android:nextFocusForward 设置指定视图获得下一个焦点
android:contentDescription 说明
android:OnClick 点击时从上下文中调用指定的方法

第三类:属性值为具体的像素值,如30dip,40px,50dp

属性 说明
android:layout_width 定义本元素的宽度
android:layout_height 定义本元素的高度
android:layout_margin 本元素离上下左右间的距离
android:layout_marginBottom 离某元素底边缘的距离
android:layout_marginLeft 离某元素左边缘的距离
android:layout_marginRight 离某元素右边缘的距离
android:layout_marginTop 离某元素上边缘的距离
android:layout_marginStart 本元素里开始的位置的距离
android:layout_marginEnd 本元素里结束位置的距离
android:scrollX 水平初始滚动偏移
android:scrollY 垂直初始滚动偏移
android:padding 指定布局与子布局的间距
android:paddingLeft 指定布局左边与子布局的间距
android:paddingTop 指定布局上边与子布局的间距
android:paddingRight 指定布局右边与子布局的间距
android:paddingBottom 指定布局下边与子布局的间距
android:paddingStart 指定布局左边与子布局的间距与android:paddingLeft相同
android:paddingEnd 指定布局右边与子布局的间距与android:paddingRight相同
android:fadingEdgeLength 设置边框渐变的长度
android:minHeight 最小高度
android:minWidth 最小宽度
android:translationX 水平方向的移动距离
android:translationY 垂直方向的移动距离
android:transformPivotX 相对于一点的水平方向偏转量
android:transformPivotY 相对于一点的垂直方向偏转量

第四类:属性值为Android内置值

属性 说明
android:gravity 控件布局方式
android:layout_gravity 布局方式
android:persistentDrawingCachehua 定义绘图的高速缓存的持久性
android:descendantFocusability 控制子布局焦点获取方式 常用于listView的item中包含多个控件点击无效
android:scrollbars 设置滚动条的状态
android:scrollbarStyle 设置滚动条的样式
android:fitsSystemWindows 设置布局调整时是否考虑系统窗口(如状态栏)
android:scrollbarFadeDuration 设置滚动条淡入淡出时间
android:scrollbarDefaultDelayBeforeFade 设置滚动条N毫秒后开始淡化,以毫秒为单位
android:scrollbarSize 设置滚动调大小
android:fadingEdge 设置拉滚动条时 ,边框渐变的放向
android:drawingCacheQuality 设置绘图时半透明质量
android:OverScrollMode 滑动到边界时样式
android:alpha 设置透明度
android:rotation 旋转度数
android:rotationX 水平旋转度数
android:rotationY 垂直旋转度数
android:scaleX 设置X轴缩放
android:scaleY 设置Y轴缩放
android:verticalScrollbarPosition 设置垂直滚动条的位置
android:layerType 设定支持
android:layoutDirection 定义布局图纸的方向
android:textDirection 定义文字方向
android:textAlignment 文字对齐方式
android:importantForAccessibility 设置可达性的重要行
android:labelFor 添加标签
android:background 本元素的背景

你可能感兴趣的:(android,view,onDraw,onLayout,onmeasure)