大家好,今天给各位分享高效包裹解决方案:提升包装效率的实用技巧的一些知识,其中也会对进行解释,文章篇幅可能偏长,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在就马上开始吧!
wrapp_content/match_parent可以让view的宽高灵活变化的秘诀是什么?
measureSpec影响宽高的计算
视图的绘制过程主要由三个部分组成:测量、布局、绘制。测量过程就是计算View的宽度和高度的过程,主要是通过onMeasure方法实现的。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
.
}onMeasure方法从父视图接收子视图宽度和高度的measureSpec约束。具体视图会根据measureSpec计算视图的宽度和高度。
measureSpec的一些概念:measureSpec是一个32位值。前两位表示测量模式,后30位表示测量大小。
共有三种测量模式:
确切地说:父控件确定子控件的特定大小。
AT_MOST:子控件最多达到指定的大小值。
UNSPECIFIED:父控件不对子控件施加任何约束,子控件可以获得任何想要的大小。
android提供了相应的方法来处理measureSpec
//获取测量模式
int specMode=MeasureSpec.getMode(measureSpec);
//获取测量的尺寸
int specSize=MeasureSpec.getSize(measureSpec);
//根据尺寸和模式生成measureSpec
MeasureSpec.makeMeasureSpec(resultSize, resultMode);例如 TextView的onMeasure实现://onMeasure关键实现
@覆盖
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode=MeasureSpec.getMode(widthMeasureSpec);
int heightMode=MeasureSpec.getMode(heightMeasureSpec);
int widthSize=MeasureSpec.getSize(widthMeasureSpec);
int heightSize=MeasureSpec.getSize(heightMeasureSpec);
if (widthMode==MeasureSpec.EXACTLY) {
//父母已经告诉我们要多大。就这样吧。
宽度=宽度尺寸;
} 别的{
.
if (widthMode==MeasureSpec.AT_MOST) {
宽度=Math.min(widthSize, 宽度);
}
}
.
if (heightMode==MeasureSpec.EXACTLY) {
//父母已经告诉我们要多大。就这样吧。
高度=高度尺寸;
mDesiredHeightAtMeasure=-1;
} 别的{
.
if (heightMode==MeasureSpec.AT_MOST) {
高度=Math.min(期望值, heightSize);
}
}
.
setMeasuredDimension(宽度,高度);
}第一的:
从父视图的约束measureSpec 获取约束的模式specMode 和约束的大小specSize。
第二:
如果mode为EXACTLY(父控件决定子控件的具体尺寸),则TextView的宽高直接是父View约束的宽高;
如果模式为AT_MOST(子控件最多达到指定大小),则取TextView自身大小和父视图约束大小的最小值;
如果是UNSPECIFIED(父控件不对子控件施加任何约束,子控件可以获得任何想要的大小),TextView将采用TextView本身的大小,无需额外处理。
因此,视图的宽度和高度的计算是由父视图传递的约束measureSpec决定的。
那么measureSpec从哪里来呢?
wrap_content/match_parent影响measureSpec的计算
父视图在自己测量时会调用子视图的onMeasure方法,测量子视图例如,以下布局:
?xml version="1.0"encoding="utf-8"?实测时序图:
image.png在measureChildWithMargins方法中调用子视图的measure方法,最终执行子视图的onMeasure方法。
protected voidmeasureChildWithMargins(View child, int ParentWidthMeasureSpec, int widthUsed,
intparentHeightMeasureSpec, int heightUsed) {
最终MarginLayoutParams lp=(MarginLayoutParams) child.getLayoutParams();
最终int childWidthMeasureSpec=getChildMeasureSpec(parentWidthMeasureSpec,
mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin + widthUsed, lp.width);
最终int childHeightMeasureSpec=getChildMeasureSpec(parentHeightMeasureSpec,
mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin + heightUsed, lp.height);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}子视图onMeasure方法所需的measureSpec是通过getChildMeasureSpec方法获取的。
公共静态int getChildMeasureSpec(int 规范, int 填充, int childDimension) {
int specMode=MeasureSpec.getMode(spec);
int specSize=MeasureSpec.getSize(spec);
int size=Math.max(0, specSize - 填充);
int 结果大小=0;
int 结果模式=0;
开关(规格模式){
//父级给我们强加了一个精确的尺寸
案例MeasureSpec.EXACTLY:
if (子维度=0) {
结果大小=子维度;
resultMode=MeasureSpec.EXACTLY;
} else if (childDimension==LayoutParams.MATCH_PARENT) {
//孩子想要成为我们的尺寸。就这样吧。
结果大小=大小;
resultMode=MeasureSpec.EXACTLY;
} else if (childDimension==LayoutParams.WRAP_CONTENT) {
//孩子想要确定自己的大小。不可能是
//比我们大。
结果大小=大小;
resultMode=MeasureSpec.AT_MOST;
}
休息;
//父级给我们施加了最大尺寸
案例MeasureSpec.AT_MOST:
if (子维度=0) {
//孩子想要一个特定的尺寸.就这样吧
结果大小=子维度;
resultMode=MeasureSpec.EXACTLY;
} else if (childDimension==LayoutParams.MATCH_PARENT) {
//孩子想要成为我们的尺寸,但我们的尺寸不固定。
//限制孩子不比我们大。
结果大小=大小;
resultMode=MeasureSpec.AT_MOST;
} else if (childDimension==LayoutParams.WRAP_CONTENT) {
//孩子想要确定自己的大小。不可能是
//比我们大。
结果大小=大小;
resultMode=MeasureSpec.AT_MOST;
}
休息;
//家长要求看看我们想要多大
案例MeasureSpec.UNSPECIFIED:
if (子维度=0) {
//孩子想要特定的尺寸.让他拥有
结果大小=子维度;
resultMode=MeasureSpec.EXACTLY;
} else if (childDimension==LayoutParams.MATCH_PARENT) {
//孩子想要成为我们的尺寸.找出它应该有多大
//是
resultSize=View.sUseZeroUnspecifiedMeasureSpec ? 0 : 大小;
resultMode=MeasureSpec.UNSPECIFIED;
} else if (childDimension==LayoutParams.WRAP_CONTENT) {
//孩子想要确定自己的大小.了解如何
//应该很大
resultSize=View.sUseZeroUnspecifiedMeasureSpec ? 0 : 大小;
resultMode=MeasureSpec.UNSPECIFIED;
}
休息;
}
//无检查资源类型
返回MeasureSpec.makeMeasureSpec(resultSize, resultMode);在getChildMeasureSpec方法中,终于看到了久违的wrap_contentmatch_parent。可以看到,子视图的measureSpec是由两部分决定的,父视图的measureSpec和子视图的LayoutParams。
如果子视图的LayoutParams宽度和高度设置为特定尺寸
.
if (子维度=0) {
结果大小=子维度;
resultMode=MeasureSpec.EXACTLY;
}
.则子视图measurerSpec约束模式为EXACTLY,约束尺寸为LayoutParams中定义的尺寸。根据前面介绍的TextView的onMeasure方法逻辑,计算出来的尺寸就是约束尺寸。
如果父视图约束模式为EXACTLY(通常将父视图的宽度和高度定义为具体尺寸),则子视图LayoutParams定义为match_parent(以填充父视图)
.
案例MeasureSpec.EXACTLY:
if (childDimension==LayoutParams.MATCH_PARENT) {
//孩子想要成为我们的尺寸。就这样吧。
结果大小=大小;
resultMode=MeasureSpec.EXACTLY;
}
.获取到的子视图的measureSpec约束方式仍然是EXACTLY,约束尺寸为父视图约束的尺寸,并且TextView计算出的宽高与父视图一样大,达到填充父视图的效果看法;
如果子视图定义为wrap_content
.
案例MeasureSpec.EXACTLY:
if (childDimension==LayoutParams.WRAP_CONTENT) {
//孩子想要确定自己的大小。不可能是
//比我们大。
结果大小=大小;
resultMode=MeasureSpec.AT_MOST;
}
.获取到的子视图的measureSpec约束模式为AT_MOST,约束大小为父视图约束的大小。 TextView计算出的宽度和高度与父视图的最小约束尺寸相同。宽度和高度由其自身尺寸决定。但不会超出父视图的约束大小。
其他的组合方法还有很多,我就不一一列举了。可以看到我们平时记忆和理解的wrap_contentmatch_parent灵活改变view的宽高的效果主要就是通过这段代码逻辑来实现的。
理解视图测量时的一些疑问:
顶层视图的measureSpec的由来
从前面的讨论可以知道,测量方法的参数measureSpec是从父视图传入的,那么顶层视图的measureSpec从哪里来呢?
我们经常给activity设置的layout布局的根视图并不是顶层视图。
我们先看一张图:
image.pngcontent 部分是为Activity 设置的布局。外层还有一个视图DecorView。这是顶层视图。
DecorView的测量过程在ViewRootImpl的performTraversals方法中。
私人无效performTraversals(){
.
//获取视图宽度和高度的测量规格,mWidth和mHeight代表窗口的宽度和高度,lp.widthhe和lp.height代表DecorView根布局的宽度和高度
int childWidthMeasureSpec=getRootMeasureSpec(mWidth, lp.width);
int childHeightMeasureSpec=getRootMeasureSpec(mHeight, lp.height);
//询问主机想要多大
//执行测量操作
执行测量(childWidthMeasureSpec,childHeightMeasureSpec);
.
//执行布局操作
执行布局(lp,desiredWindowWidth,desiredWindowHeight);
.
//执行绘图操作
执行绘图();
.
}DecorView的测量规范是通过getRootMeasureSpec方法创建的,DecorView的测量是在performMeasure方法中执行的,遍历整个子视图。
而视图的布局和绘制也是从这里开始的。通过依次执行performMeasure、performLayout、performDraw方法,完成整个页面绘制过程。
ListView对子视图测量的区别
ListView的子视图布局高度无论设置为wrap_content还是match_parent,其高度都是子视图本身的大小。这是为什么呢?
ListView中子视图的测量调用了自己定义的方法measureScrapChild。
私有无效measureScrapChild(查看孩子,int位置,int widthMeasureSpec,int heightHint){
LayoutParams p=(LayoutParams) child.getLayoutParams();
.
if (lpHeight 0) {
childHeightSpec=MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
} 别的{
childHeightSpec=MeasureSpec.makeSafeMeasureSpec(heightHint, MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec, childHeightSpec);
关于高效包裹解决方案:提升包装效率的实用技巧和的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。
【高效包裹解决方案:提升包装效率的实用技巧】相关文章:
用户评论
包装纸真方便,能保护东西不被弄脏
有9位网友表示赞同!
学习一些漂亮的包装技巧,礼物瞬间提升档次
有17位网友表示赞同!
包裹着美味的食物,更添了一份期待感
有10位网友表示赞同!
不知道为啥特别喜欢用布包裹小物件,很居家哦~
有14位网友表示赞同!
包装纸还可以DIY做装饰品,挺酷的
有13位网友表示赞同!
礼物收到之后最好是包装精美些,看着就开心!
有12位网友表示赞同!
我超讨厌去商店买东西时,包装袋总是那么薄)
有12位网友表示赞同!
如果包装太过于复杂的话会感觉很麻烦呀!
有18位网友表示赞同!
希望环保包装能够更普及一点~
有17位网友表示赞同!
现在很多店用纸盒包装很好看,很有设计感
有13位网友表示赞同!
我很喜欢自己动手包装礼物的感觉很满足!
有11位网友表示赞同!
包装纸的颜色很重要啊,看着舒服才能心情好
有13位网友表示赞同!
包裹东西的时候可以准备一些亮片或带装饰性的绳子
有7位网友表示赞同!
想学习怎么做那种精美的盒子包装
有9位网友表示赞同!
有时候收到包裹时,特别喜欢拆开包裹的过程
有13位网友表示赞同!
如果不小心把东西弄坏了,包装纸就显得很有用了
有12位网友表示赞同!
包装纸的选择和材质也很重要吧!
有20位网友表示赞同!
有些物品不适合用普通的包装纸包饰哦
有17位网友表示赞同!
包装其实也可以体现一个人的审美
有7位网友表示赞同!