Android 对ViewPager中测量实现的理解
出于一些不相关的原因,我正在浏览ViewPager的代码,我看到它覆盖了ViewGroup的onMeasure。我一直在努力学习如何正确地实现onMeasure,所以我决定仔细看看。这是供参考的方法-Android 对ViewPager中测量实现的理解,android,android-viewpager,viewgroup,onmeasure,Android,Android Viewpager,Viewgroup,Onmeasure,出于一些不相关的原因,我正在浏览ViewPager的代码,我看到它覆盖了ViewGroup的onMeasure。我一直在努力学习如何正确地实现onMeasure,所以我决定仔细看看。这是供参考的方法- @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // For simple implementation, our internal size is always 0.
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// For simple implementation, our internal size is always 0.
// We depend on the container to specify the layout size of
// our view. We can't really know what it is since we will be
// adding and removing different arbitrary views and do not
// want the layout to change as this happens.
setMeasuredDimension(getDefaultSize(0, widthMeasureSpec),
getDefaultSize(0, heightMeasureSpec));
final int measuredWidth = getMeasuredWidth();
final int maxGutterSize = measuredWidth / 10;
mGutterSize = Math.min(maxGutterSize, mDefaultGutterSize);
// Children are just made to fill our space.
int childWidthSize = measuredWidth - getPaddingLeft() - getPaddingRight();
int childHeightSize = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
/*
* Make sure all children have been properly measured. Decor views first.
* Right now we cheat and make this less complicated by assuming decor
* views won't intersect. We will pin to edges based on gravity.
*/
int size = getChildCount();
for (int i = 0; i < size; ++i) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp != null && lp.isDecor) {
final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK;
int widthMode = MeasureSpec.AT_MOST;
int heightMode = MeasureSpec.AT_MOST;
boolean consumeVertical = vgrav == Gravity.TOP || vgrav == Gravity.BOTTOM;
boolean consumeHorizontal = hgrav == Gravity.LEFT || hgrav == Gravity.RIGHT;
if (consumeVertical) {
widthMode = MeasureSpec.EXACTLY;
} else if (consumeHorizontal) {
heightMode = MeasureSpec.EXACTLY;
}
int widthSize = childWidthSize;
int heightSize = childHeightSize;
if (lp.width != LayoutParams.WRAP_CONTENT) {
widthMode = MeasureSpec.EXACTLY;
if (lp.width != LayoutParams.MATCH_PARENT) {
widthSize = lp.width;
}
}
if (lp.height != LayoutParams.WRAP_CONTENT) {
heightMode = MeasureSpec.EXACTLY;
if (lp.height != LayoutParams.MATCH_PARENT) {
heightSize = lp.height;
}
}
final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode);
final int heightSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode);
child.measure(widthSpec, heightSpec);
if (consumeVertical) {
childHeightSize -= child.getMeasuredHeight();
} else if (consumeHorizontal) {
childWidthSize -= child.getMeasuredWidth();
}
}
}
}
mChildWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY);
mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightSize, MeasureSpec.EXACTLY);
// Make sure we have created all fragments that we need to have shown.
mInLayout = true;
populate();
mInLayout = false;
// Page views next.
size = getChildCount();
for (int i = 0; i < size; ++i) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
if (DEBUG) {
Log.v(TAG, "Measuring #" + i + " " + child + ": " + mChildWidthMeasureSpec);
}
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (lp == null || !lp.isDecor) {
final int widthSpec = MeasureSpec.makeMeasureSpec(
(int) (childWidthSize * lp.widthFactor), MeasureSpec.EXACTLY);
child.measure(widthSpec, mChildHeightMeasureSpec);
}
}
}
}
@覆盖
测量时的保护空隙(内部宽度测量等级、内部高度测量等级){
//对于简单的实现,我们的内部大小始终为0。
//我们依赖容器来指定
//我们的观点。我们不能真正知道它是什么,因为我们将
//添加和删除不同的任意视图,而不
//希望在发生这种情况时更改布局。
setMeasuredDimension(getDefaultSize(0,widthMeasureSpec),
getDefaultSize(0,heightMeasureSpec));
最终int measuredWidth=getMeasuredWidth();
最终整数maxGutterSize=测量宽度/10;
MGuttSize=Math.min(maxGutterSize,mDefaultGutterSize);
//孩子只是为了填满我们的空间。
int childWidthSize=measuredWidth-getPaddingLeft()-getPaddingRight();
int childHeightSize=getMeasuredHeight()-getPaddingTop()-getPaddingBottom();
/*
*确保所有的孩子都被正确地测量过。首先是装饰视图。
*现在我们作弊,通过装潢使事情变得不那么复杂
*视图不会相交。我们将基于重力固定到边上。
*/
int size=getChildCount();
对于(int i=0;i
我无法理解处理装饰视图的重要性背后的逻辑。据我所知,如果有两个子视图-一个是重力左上角,另一个是右上角,代码将从childHeightSize中减去两个子视图的高度。对我来说,这似乎是错误的,因为逻辑应该只减去具有最大高度的子视图的高度
为什么要这样实施