美文网首页
android基本原理-view的显示总结

android基本原理-view的显示总结

作者: bccd80056cc7 | 来源:发表于2018-06-21 15:46 被阅读11次

View的常用回调:onAttachedToWindow(),onVisibilityChanged(),onDetachedFromWindow()
和window相关的两个方法可以用来做变量的初始化和回收,比如监听事件的添加和释放
中间的可见性变化,个人用到是因为定制的framework有缺陷,规避缺陷。

自定义view分为两种:

  • 继承现有ViewGroup,实现组合控件,按需添加自定义属性、业务等。
  • 继承View(Group),略加修改,添加业务或者重写onMeasure等方法

界面流程:
activity创建之后,会添加DectorView到Window中,同时会创建ViewRoot(以ViewRootImpl对象的形式),并将两者关联起来。

setContentView()是因为DecorView作为顶级View(FrameLayout),一般包含一个LinearLayout,分为标题和内容,而内容就是content,对应布局id是android.R.id.content

而View的绘制,则是通过ViewRoot执行performTraversals开始。包括performMeasure-->measure-->onMeasure-->performLayout-->layout-->onLayout-->performDraw-->draw-->onDraw

View的测量,通过MeasureSpec转化,而MeasureSpec的确定,则通过外层限制和自身属性确定。比如DecorView由窗口尺寸和自身LayoutParams确定;常规View由父容器的MeasureSpec和LayoutParams确定。

onMeasure:
View里面调用getDefaultSize计算测量值,该方法表明:Unspecified的情况下,取最小宽度、背景最小宽度(原始宽度)的大值,否则取parentSpecSize。再把测量值赋值给变量mMeasuredWidth,...;

可以看到AT_MOST和EXACTLY取的值都是parentSpecSize。所以自己继承view的时候,需要在onMeasure中处理wrap_content的情况,给与默认的宽/高,而具体值没有给定依据。

而ViewGroup则是结合模式和子View的宽高进行设置。可以自己翻看

onMeasure之后,可以getMeasuredWidth和getMeasuredHeight

因为activity生命周期和View的测量不是同步的,所以在onResume之前不能保证View已经执行完onMeasure。可以用这几个方法解决:activity/view#onWindowFocusChanged,view#post,ViewTreeObserver,view.measure(match_parent的时候不能做到,具体数值的时候传入EXACTLY和尺寸即可,wrap的时候传入AT_MOST和(1<<30)-1)

onLayout:
setFrame和layout递归调用

onLayout之后,可以getWidth和getHeight

getMeasuredWidth和getWidth赋值的时间不同,值在默认情况(即正常的layout)下相同。

onDraw:
绘制背景background.draw,绘制自己onDraw,绘制子视图dispatchDraw,绘制装饰onDrawScrollBars

setWillNotDraw。在有些ViewGroup中被置为true,自己处理的时候注意

MeasureSpec:
View的静态内部类,将模式和大小值存储在一个int值中,前2位代表模式SpecMode,后30位代表大小SpecSize。

模式 对应LayoutParams 说明
UNSPECIFIED / 父类未对子类约束,可以为任何值
EXACTLY match_parent和具体的值 已检测出大小,即SpecSize的值
AT_MOST wrap_content 已指定最大值SpecSize

遗留问题:
1、View的makeMeasureSpec()中,sUseBrokenMakeMeasureSpec会在<=17的时候置为true,理由是RelativeLayout的兼容性:

        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
                                          @MeasureSpecMode int mode) {
            if (sUseBrokenMakeMeasureSpec) {
                return size + mode;
            } else {
                return (size & ~MODE_MASK) | (mode & MODE_MASK);
            }
        }

那么问题就是,为什么会有兼容性问题,因为size可能为负?
2、为什么getDefaultSize中AT_MOST和EXACTLY返回大小都是parentSpecSize?感觉完全可以做到父类中区分?

摘自:
开发艺术探索,第4章,view的工作原理

相关文章

网友评论

      本文标题:android基本原理-view的显示总结

      本文链接:https://www.haomeiwen.com/subject/catfyftx.html