网站建设哪家,wordpress 密码访问,合肥市做外贸网站的公司,创造一个网页一、UI如何进行具体绘制
UI从数据加载到具体展现的过程#xff1a; 进程间的启动协作#xff1a; 二、如何加载到数据
应用从启动到onCreate的过程#xff1a; Activity生产过程详解#xff1a; 核心对象 绘制流程源码路径
1、Activity加载ViewRootImpl
ActivityThread…一、UI如何进行具体绘制
UI从数据加载到具体展现的过程 进程间的启动协作 二、如何加载到数据
应用从启动到onCreate的过程 Activity生产过程详解 核心对象 绘制流程源码路径
1、Activity加载ViewRootImpl
ActivityThread.handleResumeActivity()
-- WindowManagerImpl.addView(decorView, layoutParams)
-- WindowManagerGlobal.addView()2、ViewRootImpl启动View树的遍历
ViewRootImpl.setView(decorView, layoutParams, parentView)
--ViewRootImpl.requestLayout()
--scheduleTraversals()
--TraversalRunnable.run()
--doTraversal()
--performTraversals()performMeasure、performLayout、performDraw二、View绘制流程
1、measure
1MeasureSpec是什么
重写过onMeasure()方法都知道测量需要用到MeasureSpec类获取View的测量模式和大小那么这个类是怎样存储这两个信息呢
留心观察的话会发现onMeasure方法的两个参数实际是32位int类型数据即 00 000000 00000000 00000000 00000000 而其结构为 mode size 前2位为mode而后30位为size。 getMode()方法measureSpec -- mode
private static final int MODE_SHIFT 30;
// 0x3转换为二进制即为11
// 左移30位后11000000 00000000 00000000 00000000
private static final int MODE_MASK 0x3 MODE_SHIFT;public static int getMode(int measureSpec) {// 与MODE_MASK按位与运算后即将低30位清零结果为mode左移30位后的值return (measureSpec MODE_MASK);
}getSize()方法同理。 makeMeasureSpec()方法mode size -- measureSpec
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位清零后的结果右侧为mode的低30位清零后的结果两者按位或运算的结果正好为高2位mode、低30位size例
01000000 00000000 00000000 00000000 |
00001000 00001011 11110101 10101101
01001000 00001011 11110101 10101101测量模式
public static final int UNSPECIFIED 0 MODE_SHIFT;
public static final int EXACTLY 1 MODE_SHIFT;
public static final int AT_MOST 2 MODE_SHIFT;UNSPECIFIED父容器不对View作任何限制系统内部使用。
EXACTLY精确模式父容器检测出View大小即为SpecSize对应LayoutParams中的match_parent和指定大小的情况。
AT_MOST最大模式父容器指定可用大小View的大小不能超出这个值对应wrap_content。
2ViewGroup的测量流程
回到ViewRootImpl的performMeasure方法这里传入的参数为顶层DecorView的测量规格其测量方式为
private static int getRootMeasureSpec(int windowSize, int rootDimension) {int measureSpec;switch (rootDimension) {case ViewGroup.LayoutParams.MATCH_PARENT:measureSpec MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY);break;case ViewGroup.LayoutParams.WRAP_CONTENT:measureSpec MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST);break;default:measureSpec MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY);break;}return measureSpec;
}match_parent和具体数值大小为EXACTLY模式wrap_content则为AT_MOST模式。
往下走performMeasure方法中调用了DecorView的onMeasure方法而DecorView继承自FrameLayout可以看到FL的onMeasure方法中调用了measureChildWithMargins方法并传入自身的测量规格
protected void measureChildWithMargins(View child,int parentWidthMeasureSpec, int widthUsed,int parentHeightMeasureSpec, int heightUsed) {final MarginLayoutParams lp (MarginLayoutParams) child.getLayoutParams();final int childWidthMeasureSpec getChildMeasureSpec(parentWidthMeasureSpec,mPaddingLeft mPaddingRight lp.leftMargin lp.rightMargin widthUsed, lp.width);final int childHeightMeasureSpec getChildMeasureSpec(parentHeightMeasureSpec,mPaddingTop mPaddingBottom lp.topMargin lp.bottomMargin heightUsed, lp.height);child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}即测量子控件的大小测量规则详情可看getChildMeasureSpec方法总结如下
childLayoutParams\parentSpecModeEXACTLYAT_MOSTUNSPECIFIEDdpEXACTLY/childSizeEXACTLY/childSizeEXCATLY/childSizematch_parentEXACTLY/parentSizeAT_MOST/parentSizeUNSPECIFIED/0wrap_contentAT_MOST/parentSizeAT_MOST/parentSizeUNSPECIFIED/0
回到onMeasure方法测完子控件之后ViewGroup会经过一些计算得出自身大小
// 加上padding
maxWidth getPaddingLeftWithForeground() getPaddingRightWithForeground();
maxHeight getPaddingTopWithForeground() getPaddingBottomWithForeground();// 检查是否小于最小宽度、最小高度
maxHeight Math.max(maxHeight, getSuggestedMinimumHeight());
maxWidth Math.max(maxWidth, getSuggestedMinimumWidth());// 检查Drawable的最小高度和宽度
final Drawable drawable getForeground();
if (drawable ! null) {maxHeight Math.max(maxHeight, drawable.getMinimumHeight());maxWidth Math.max(maxWidth, drawable.getMinimumWidth());
}setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),resolveSizeAndState(maxHeight, heightMeasureSpec,childState MEASURED_HEIGHT_STATE_SHIFT));综上ViewGroup的测量需要先测量子View的大小而后结合padding等属性计算得出自身大小。
3View的测量流程
View.performMeasure()
--onMeasure(int widthMeasureSpec, int heightMeasureSpec)
--setMeasuredDimension(int measuredWidth, int measuredHeight)
--setMeasuredDimensionRaw(int measuredWidth, int measuredHeight)可以看到setMeasuredDimensionRaw()方法
private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {// 存储测量结果mMeasuredWidth measuredWidth;mMeasuredHeight measuredHeight;// 设置测量完成的标志位mPrivateFlags | PFLAG_MEASURED_DIMENSION_SET;
}View不需要考虑子View的大小根据内容测量得出自身大小即可。
另外View中的onMeasure方法中调用到getDefaultSize方法
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}public static int getDefaultSize(int size, int measureSpec) {int result size;int specMode MeasureSpec.getMode(measureSpec);int specSize MeasureSpec.getSize(measureSpec);switch (specMode) {case MeasureSpec.UNSPECIFIED:result size;break;case MeasureSpec.AT_MOST:case MeasureSpec.EXACTLY:// 最终测量的结果都是父容器的大小result specSize;break;}return result;
}这里看到精确模式和最大模式最终测量的结果都是父容器的大小即布局中的wrap_content、match_parent以及数值大小效果都一样这也就是自定义View一定要重写onMeasure方法的原因。
2、layout
布局相对测量而言要简单许多从ViewRootImpl的performLayout方法出发可以看到其中调用了DecorView的layout方法
// 实则为DecorView的left, top, right, bottom四个信息
host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());进入layout方法发现l、t、r、b被传递到了setFrame方法中并设置给了成员变量
mLeft left;
mTop top;
mRight right;
mBottom bottom;所以布局实际为调用View的layout方法设置自身的l、t、r、b值。另外layout方法中往下走可以看到调用了onLayout方法进入后发现为空方法。因而查看FrameLayout的onLayout方法
Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {layoutChildren(left, top, right, bottom, false /* no force left gravity */);
}void layoutChildren(int left, int top, int right, int bottom, boolean forceLeftGravity) {final int count getChildCount();// 省略for (int i 0; i count; i) {final View child getChildAt(i);if (child.getVisibility() ! GONE) {final LayoutParams lp (LayoutParams) child.getLayoutParams();// 省略child.layout(childLeft, childTop, childLeft width, childTop height);}}
}可以看到进行一系列计算后调用了child的layout方法对子控件进行布局同时子控件又会继续往下对自己的子控件布局从而实现遍历。
综上布局实际为调用layout方法设置View位置ViewGroup则需要另外实现onLayout方法摆放子控件。
3、draw
1绘制过程入口
ViewRootImpl.performDraw()
--ViewRootImpl.draw()
--ViewRootImpl.drawSoftware()
--View.draw()2绘制步骤
进入到View的draw方法中可以看到以下一段注释
/** Draw traversal performs several drawing steps which must be executed* in the appropriate order:** 1. Draw the background* 2. If necessary, save the canvas layers to prepare for fading* 3. Draw views content* 4. Draw children* 5. If necessary, draw the fading edges and restore layers* 6. Draw decorations (scrollbars for instance)*/以上就是Android开发中的UI绘制原理及过程实现更多技术探讨可进入查看《Android核心技术手册》进行学习。
最后
结合draw方法的源码绘制过程的关键步骤如下 绘制背景drawBackground(canvas) 绘制自己onDraw(canvas) 绘制子viewdispatchDraw(canvas) 绘制滚动条、前景等装饰onDrawForeground(canvas)
文章转载自: http://www.morning.xfdkh.cn.gov.cn.xfdkh.cn http://www.morning.jltmb.cn.gov.cn.jltmb.cn http://www.morning.qcwck.cn.gov.cn.qcwck.cn http://www.morning.nzlsm.cn.gov.cn.nzlsm.cn http://www.morning.mywnk.cn.gov.cn.mywnk.cn http://www.morning.mfrb.cn.gov.cn.mfrb.cn http://www.morning.gprzp.cn.gov.cn.gprzp.cn http://www.morning.rczrq.cn.gov.cn.rczrq.cn http://www.morning.glpxx.cn.gov.cn.glpxx.cn http://www.morning.krjrb.cn.gov.cn.krjrb.cn http://www.morning.yxwcj.cn.gov.cn.yxwcj.cn http://www.morning.qtltg.cn.gov.cn.qtltg.cn http://www.morning.ntwxt.cn.gov.cn.ntwxt.cn http://www.morning.jwwfk.cn.gov.cn.jwwfk.cn http://www.morning.npbnc.cn.gov.cn.npbnc.cn http://www.morning.jkzjs.cn.gov.cn.jkzjs.cn http://www.morning.ryzgp.cn.gov.cn.ryzgp.cn http://www.morning.piekr.com.gov.cn.piekr.com http://www.morning.fwcnx.cn.gov.cn.fwcnx.cn http://www.morning.nrydm.cn.gov.cn.nrydm.cn http://www.morning.rxnxl.cn.gov.cn.rxnxl.cn http://www.morning.wfyqn.cn.gov.cn.wfyqn.cn http://www.morning.brscd.cn.gov.cn.brscd.cn http://www.morning.xnflx.cn.gov.cn.xnflx.cn http://www.morning.zympx.cn.gov.cn.zympx.cn http://www.morning.kfsfm.cn.gov.cn.kfsfm.cn http://www.morning.ydhck.cn.gov.cn.ydhck.cn http://www.morning.qnlbb.cn.gov.cn.qnlbb.cn http://www.morning.srjgz.cn.gov.cn.srjgz.cn http://www.morning.zjqwr.cn.gov.cn.zjqwr.cn http://www.morning.sbrrf.cn.gov.cn.sbrrf.cn http://www.morning.snbry.cn.gov.cn.snbry.cn http://www.morning.mdmc.cn.gov.cn.mdmc.cn http://www.morning.rknjx.cn.gov.cn.rknjx.cn http://www.morning.ltpph.cn.gov.cn.ltpph.cn http://www.morning.jngdh.cn.gov.cn.jngdh.cn http://www.morning.bksbx.cn.gov.cn.bksbx.cn http://www.morning.fengnue.com.gov.cn.fengnue.com http://www.morning.zmlbq.cn.gov.cn.zmlbq.cn http://www.morning.fkgqn.cn.gov.cn.fkgqn.cn http://www.morning.zylrk.cn.gov.cn.zylrk.cn http://www.morning.ggtgl.cn.gov.cn.ggtgl.cn http://www.morning.wxgd.cn.gov.cn.wxgd.cn http://www.morning.rdxnt.cn.gov.cn.rdxnt.cn http://www.morning.jzfrl.cn.gov.cn.jzfrl.cn http://www.morning.bojkosvit.com.gov.cn.bojkosvit.com http://www.morning.gzttoyp.com.gov.cn.gzttoyp.com http://www.morning.jkmjm.cn.gov.cn.jkmjm.cn http://www.morning.ztcwp.cn.gov.cn.ztcwp.cn http://www.morning.bkryb.cn.gov.cn.bkryb.cn http://www.morning.hdzty.cn.gov.cn.hdzty.cn http://www.morning.lkmks.cn.gov.cn.lkmks.cn http://www.morning.nqgjn.cn.gov.cn.nqgjn.cn http://www.morning.lcplz.cn.gov.cn.lcplz.cn http://www.morning.pxtgf.cn.gov.cn.pxtgf.cn http://www.morning.bssjp.cn.gov.cn.bssjp.cn http://www.morning.pbzgj.cn.gov.cn.pbzgj.cn http://www.morning.pwlxy.cn.gov.cn.pwlxy.cn http://www.morning.lgpzq.cn.gov.cn.lgpzq.cn http://www.morning.ztcwp.cn.gov.cn.ztcwp.cn http://www.morning.rchsr.cn.gov.cn.rchsr.cn http://www.morning.rkdhh.cn.gov.cn.rkdhh.cn http://www.morning.wxccm.cn.gov.cn.wxccm.cn http://www.morning.drswd.cn.gov.cn.drswd.cn http://www.morning.knqck.cn.gov.cn.knqck.cn http://www.morning.pnjsl.cn.gov.cn.pnjsl.cn http://www.morning.nxpqw.cn.gov.cn.nxpqw.cn http://www.morning.rwqj.cn.gov.cn.rwqj.cn http://www.morning.hymmq.cn.gov.cn.hymmq.cn http://www.morning.mttqp.cn.gov.cn.mttqp.cn http://www.morning.fpqq.cn.gov.cn.fpqq.cn http://www.morning.bgnkl.cn.gov.cn.bgnkl.cn http://www.morning.pctsq.cn.gov.cn.pctsq.cn http://www.morning.gkmwk.cn.gov.cn.gkmwk.cn http://www.morning.cjqqj.cn.gov.cn.cjqqj.cn http://www.morning.sqskm.cn.gov.cn.sqskm.cn http://www.morning.rnmc.cn.gov.cn.rnmc.cn http://www.morning.dmzzt.cn.gov.cn.dmzzt.cn http://www.morning.zfqr.cn.gov.cn.zfqr.cn http://www.morning.wcgfy.cn.gov.cn.wcgfy.cn