FrameLayout 测量过程(代码流水线)
来源:互联网 发布:海子为什么卧轨知乎 编辑:程序博客网 时间:2024/05/16 08:28
/** * {@inheritDoc} * 如果,子 view如果设置属性是 match_parent, * 如果,measureMatchParentChildren是true (其实就是framlayout模式是非精准模式) * 那么这种子view是被测量了两次 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int count = getChildCount(); //当FrameLayout的宽和高 只有同时设置为 match_parent //当FrameLayout的宽和高 指定的size ///measureMatchParentChlidren = false,否则为true。 //MeasureSpec.EXACTLY时,就表示当前视图的大小等于参数measureSpec中所指定的值。 //当FrameLayout 非精准模式,这时候要把所有宽高设置为 //match_parent的子View都记录下来 // 这时候FrameLayout的宽高同时受子View的影响 final boolean measureMatchParentChildren = MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY || MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY; mMatchParentChildren.clear(); int maxHeight = 0; int maxWidth = 0; int childState = 0;//宽高的期望类型 //测量孩子同时,计算出一个最大宽高 for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (mMeasureAllChildren || child.getVisibility() != GONE) { //一次遍历每一个不为GONE的子view //第一次测量孩子 measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); final LayoutParams lp = (LayoutParams) child.getLayoutParams(); maxWidth = Math.max(maxWidth, child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin); maxHeight = Math.max(maxHeight, child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin); childState = combineMeasuredStates(childState, child.getMeasuredState()); //的mMatchParentChlidren的list里存的是设置为match_parent的子view。 if (measureMatchParentChildren) { if (lp.width == LayoutParams.MATCH_PARENT || lp.height == LayoutParams.MATCH_PARENT) { mMatchParentChildren.add(child); } } } } // Account for padding too //加上父亲的padidng maxWidth += getPaddingLeftWithForeground() + getPaddingRightWithForeground(); maxHeight += getPaddingTopWithForeground() + getPaddingBottomWithForeground(); // Check against our minimum height and width // 校验最小宽高 maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); // Check against our foreground's minimum height and width // 与前景图片比较,获取宽高相对较大的值 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)); //上面的测量,得到了framlayout的宽,高,下面,需要根据宽高,重新测量子view - 主要是 match_parent 属性的孩子 //子view中设定为match_parent的个数 //重新测量 count = mMatchParentChildren.size(); if (count > 1) { for (int i = 0; i < count; i++) { final View child = mMatchParentChildren.get(i); final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); final int childWidthMeasureSpec; //将属性为match_parent的再测量一遍 if (lp.width == LayoutParams.MATCH_PARENT) {//子view的宽是match_parent,则宽度期望值是总宽度-padding-margin final int width = Math.max(0, getMeasuredWidth() - getPaddingLeftWithForeground() - getPaddingRightWithForeground() - lp.leftMargin - lp.rightMargin); childWidthMeasureSpec = MeasureSpec.makeMeasureSpec( width, MeasureSpec.EXACTLY); } else { childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, getPaddingLeftWithForeground() + getPaddingRightWithForeground() + lp.leftMargin + lp.rightMargin, lp.width); } //将属性为match_parent的再测量一遍 final int childHeightMeasureSpec; if (lp.height == LayoutParams.MATCH_PARENT) { final int height = Math.max(0, getMeasuredHeight() - getPaddingTopWithForeground() - getPaddingBottomWithForeground() - lp.topMargin - lp.bottomMargin); childHeightMeasureSpec = MeasureSpec.makeMeasureSpec( height, MeasureSpec.EXACTLY); } else { childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, getPaddingTopWithForeground() + getPaddingBottomWithForeground() + lp.topMargin + lp.bottomMargin, lp.height); } //子view的宽是match_parent,则宽度期望值是总宽度-padding-margin // //把这部分子view重新计算大小 child.measure(childWidthMeasureSpec, childHeightMeasureSpec); } } }
protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); //根据parentWidthMeasureSpec,ViewGroup剩余宽度,child的宽度重新计算child的widthMeasureSpec 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); }
/** * @param spec The requirements for this view * parentHeightMeasureSpec * @param padding The padding of this view for the current dimension and * margins, if applicable * 父亲已经用的 + 父亲的pading + 父亲的margin * @param childDimension How big the child wants to be in the current * dimension * @return a MeasureSpec integer for the child * 孩子的布局参数 */ public static int getChildMeasureSpec(int spec, int padding, int childDimension) { //得到父亲的测量模式和大小 int specMode = MeasureSpec.getMode(spec); int specSize = MeasureSpec.getSize(spec); //父亲大小 - 父亲的冗余 //当前父View还剩的空间大小 int size = Math.max(0, specSize - padding); int resultSize = 0; int resultMode = 0; switch (specMode) { // Parent has imposed an exact size on us case MeasureSpec.EXACTLY:// 父View强制设置了一个大小给子View if (childDimension >= 0) {//大小就是 孩子参数的大小 resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.MATCH_PARENT) {//大小就是 父亲剩余空间的大小 // Child wants to be our size. So be it. resultSize = size; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.WRAP_CONTENT) {//大小设置为父亲剩余空间大小,意味着让子View去处理,子View最大的大小不能超过父View // Child wants to determine its own size. It can't be // bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } break; // Parent has imposed a maximum size on us case MeasureSpec.AT_MOST:// 父View给子View一个限定的大小,子View不能超过这个大小 if (childDimension >= 0) {// 子View的size设置成XML中配置的大小 // Child wants a specific size... so be it resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.MATCH_PARENT) {// 子View的大小为父View的size 意味着让子View去处理,子View最大的大小不能超过父View // Child wants to be our size, but our size is not fixed. // Constrain child to not be bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } else if (childDimension == LayoutParams.WRAP_CONTENT) {//同上 // Child wants to determine its own size. It can't be // bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } break; // Parent asked to see how big we want to be case MeasureSpec.UNSPECIFIED:// 意味着子View要多大都可以 if (childDimension >= 0) {//子View的size设置成XML中配置的大小 // Child wants a specific size... let him have it resultSize = childDimension; resultMode = MeasureSpec.EXACTLY;//意味着,我可以给让你想显示多大就显示多大,但是在XML中或者addView的时候, 写死了childDimension,那么它的大小就这么大吧 } else if (childDimension == LayoutParams.MATCH_PARENT) {//意味着大小让它自己决定到底要多大,随便多大都可以 // Child wants to be our size... find out how big it should // be resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size; resultMode = MeasureSpec.UNSPECIFIED; } else if (childDimension == LayoutParams.WRAP_CONTENT) {// 意味着大小让它自己决定到底要多大,随便多大都可以 // Child wants to determine its own size.... find out how // big it should be resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size; resultMode = MeasureSpec.UNSPECIFIED; } break; } return MeasureSpec.makeMeasureSpec(resultSize, resultMode); }
阅读全文
0 0
- FrameLayout 测量过程(代码流水线)
- RelativeLayout 测量过程(代码流水线)
- FrameLayout的测量
- 用代码实现FrameLayout
- FrameLayout measure过程源码Log全解析之二:修改framework代码,输出Log
- FrameLayout measure过程源码Log全解析之三:onMeasure代码概览
- ARM7的三级流水线过程
- ARM7的三级流水线过程
- ARM7的三级流水线过程
- ARM7的三级流水线过程
- LinearLayout测量过程疑问
- LinearLayout测量过程分析
- Android View 测量过程
- android FrameLayout.LayoutParams代码编程
- 什么是流水线友好的代码?
- 什么是流水线友好的代码?
- Android 自定义View 之测量过程(onMeasure)
- FrameLayout布局(1)
- ubuntu 停留开机界面解决方法
- [Unity&UGUI]UGUI的分层显示顺序是什么
- oracle CASB-云之天眼
- 求最长递增子序列
- linux的 /etc/passwd文件
- FrameLayout 测量过程(代码流水线)
- 手机网页h5实现介绍页,支持手势识别。
- IntelliJ IDEA/WebStorm/Pycharm 2016/2017 免费激活方法(免破解)
- vsftpd配置虚拟用户为登录用户
- Java笔记
- eclipse 运行的时候提示adb.exe已停止处理办法
- 比特币系统采用的公钥密码学方案和ECDSA签名算法介绍——第一部分:原理
- java 生成验证码
- 【ROS书籍】ROSByExampleⅡ——第二章 安装ROS-BY-EXAMPLE代码