掌握Android测量:从基础到进阶的Measure详解攻略

引言
在Android开发中,理解并掌握View的测量机制是至关重要的。Android中的View是通过measure过程来确定其大小的,这一过程直接影响到布局的显示和性能。本文将从基础到进阶,详细讲解Android中的测量机制。
基础概念
Measure过程
Android中的measure过程是View确定其大小和位置的关键步骤。这个过程在
View
类的
onMeasure
方法中进行,而具体的实现则由子类根据需要重写。
MeasureSpec
MeasureSpec
是一个描述尺寸和模式的类,它包含了尺寸值和模式。尺寸值可以是精确的,也可以是最大值。模式有以下几种:
MeasureSpec.EXACTLY
:表示尺寸已经确定,必须是这个值。
MeasureSpec.AT_MOST
:表示尺寸有一个最大值,但不能超过这个值。
MeasureSpec.UNSPECIFIED
:表示尺寸没有限制。
基础测量
父View测量子View
在measure过程中,父View会调用子View的
onMeasure
方法,并传递两个
MeasureSpec
对象:一个是自己的测量模式,另一个是自己的测量尺寸。
子View测量自己
子View在接收到父View的测量需求后,会根据自身的布局参数和父View提供的
MeasureSpec
来决定自己的大小。
实例:LinearLayout的measure方法
LinearLayout的measure方法会遍历所有的子View,并根据子View的measure结果来决定整个LinearLayout的大小。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);

int maxWidth = 0;
int maxHeight = 0;

for (int i = 0; i < mChildCount; i++) { final View child = mChildren[i]; if (child.getVisibility() == GONE) { continue; } final LayoutParams lp = child.getLayoutParams(); int childWidthMeasureSpec; int childHeightMeasureSpec; if (mOrientation == VERTICAL) { childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, mPaddingTop + mPaddingBottom + getPaddingTop() + getPaddingBottom(), lp.height); } else { childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY); childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, mPaddingLeft + mPaddingRight + getPaddingLeft() + getPaddingRight(), lp.width); } child.measure(childWidthMeasureSpec, childHeightMeasureSpec); maxWidth = Math.max(maxWidth, child.getMeasuredWidth()); maxHeight = Math.max(maxHeight, child.getMeasuredHeight()); } if (mOrientation == VERTICAL) { setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec), resolveSizeAndState(maxHeight, heightMeasureSpec)); } else { setMeasuredDimension(resolveSizeAndState(maxHeight, heightMeasureSpec), resolveSizeAndState(maxWidth, widthMeasureSpec)); } } 进阶测量 自定义View的测量 在自定义View时,需要重写 onMeasure 方法,并根据需要处理不同的 MeasureSpec 模式。 宽度和高度指定 在 onMeasure 方法中,可以通过 MeasureSpec.makeMeasureSpec 方法来创建一个 MeasureSpec 对象,其中包含了尺寸值和模式。 避免过度绘制 在measure过程中,如果View的大小没有发生变化,可以通过重写 shouldResize 方法来避免不必要的measure操作。 @Override protected boolean shouldResize() { final int widthSpec = getLayoutParams().width; final int heightSpec = getLayoutParams().height; return (widthSpec != MeasureSpec.EXACTLY || heightSpec != MeasureSpec.EXACTLY); } 总结 掌握Android的测量机制对于开发高性能的Android应用至关重要。本文从基础到进阶,详细讲解了Android中的测量过程,包括MeasureSpec、measure过程以及自定义View的测量等。希望本文能帮助读者更好地理解和应用Android的测量机制。