android listview onmeasure,android自定義控件(一)MeasureSpec 與 ListView.onMeasure

A MeasureSpec encapsulates the layout requirements passed from parent to child. Each MeasureSpec represents a requirement

for either the width or the height. A MeasureSpec is comprised of a size and a mode. There are three possible modes:

UNSPECIFIED

The parent has not imposed any constraint on the child. It can be whatever size it wants.

EXACTLY

The parent has determined an exact size for the child. The child is going to be given those bounds regardless of how big it wants to be.

AT_MOST

The child can be as large as it wants up to the specified size.

1.使用 View.resolveSize(int size,int measureSpec)

public static int resolveSize(int size, intmeasureSpec) {int result =size;int specMode =MeasureSpec.getMode(measureSpec);int specSize =MeasureSpec.getSize(measureSpec);switch(specMode) {caseMeasureSpec.UNSPECIFIED:

result=size;break;caseMeasureSpec.AT_MOST:

result=Math.min(size, specSize);break;caseMeasureSpec.EXACTLY:

result=specSize;break;

}returnresult;

}

2.源碼

public static classMeasureSpec {private static final int MODE_SHIFT = 30;private static final int MODE_MASK = 0x3 <

}public static int getMode(intmeasureSpec) {return (measureSpec &MODE_MASK);

}public static int getSize(intmeasureSpec) {return (measureSpec & ~MODE_MASK);

}}

示例:

int measureSpec = makeMeasureSpec(4, EXACTLY);

getSize(measureSpec);

getMode(measureSpec);

-----------------------makeMeasureSpec --------------------- mode+size

mode:            1000  0000  0000  0000  0000  0000  0000  000

size:                                       100

measureSpec: 1000  0000  0000  0000  0000  0000  0000  100

---------------getMode  ---------------- MODE_MASK & measureSpec

MODE_MASK:  1100  0000  0000  0000  0000  0000  0000  0000

measureSpec:  1000  0000  0000  0000  0000  0000  0000  100

3.示例ListView.measureItem(View child)

private voidmeasureItem(View child) {

ViewGroup.LayoutParams p=child.getLayoutParams();if (p == null) {

p= newViewGroup.LayoutParams(

ViewGroup.LayoutParams.MATCH_PARENT,

ViewGroup.LayoutParams.WRAP_CONTENT);

}int childWidthSpec =ViewGroup.getChildMeasureSpec(mWidthMeasureSpec,

mListPadding.left+mListPadding.right, p.width);int lpHeight =p.height;intchildHeightSpec;if (lpHeight > 0) {

childHeightSpec=MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);

}else{

childHeightSpec= MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);

}

child.measure(childWidthSpec, childHeightSpec);

}

4.重寫ListView與ScrollView 兼容:

protected voidonMeasure (int widthMeasureSpec, int heightMeasureSpec)

Parameters

widthMeasureSpec horizontal space requirements as imposed by the parent. The requirements are encoded with View.MeasureSpec.

heightMeasureSpec vertical space requirements as imposed by the parent. The requirements are encoded with View.MeasureSpec.

重寫:

public void onMeasure(int widthMeasureSpec, intheightMeasureSpec) {int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);super.onMeasure(widthMeasureSpec, expandSpec);

}

ListView

@Overrideprotected void onMeasure(int widthMeasureSpec, intheightMeasureSpec) {//Sets up mListPadding

super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthMode =MeasureSpec.getMode(widthMeasureSpec);int heightMode =MeasureSpec.getMode(heightMeasureSpec);int widthSize =MeasureSpec.getSize(widthMeasureSpec);int heightSize =MeasureSpec.getSize(heightMeasureSpec);int childWidth = 0;int childHeight = 0;

mItemCount= mAdapter == null ? 0: mAdapter.getCount();if (mItemCount > 0 && (widthMode == MeasureSpec.UNSPECIFIED ||heightMode==MeasureSpec.UNSPECIFIED)) {final View child = obtainView(0);

measureScrapChild(child,0, widthMeasureSpec);

childWidth=child.getMeasuredWidth();

childHeight=child.getMeasuredHeight();if(recycleOnMeasure()) {

mRecycler.addScrapView(child);

}

}if (widthMode ==MeasureSpec.UNSPECIFIED) {

widthSize= mListPadding.left + mListPadding.right + childWidth +getVerticalScrollbarWidth();

}if (heightMode ==MeasureSpec.UNSPECIFIED) {

heightSize= mListPadding.top + mListPadding.bottom + childHeight +getVerticalFadingEdgeLength()* 2;

}if (heightMode ==MeasureSpec.AT_MOST) {//TODO: after first layout we should maybe start at the first visible position, not 0

heightSize = measureHeightOfChildren(widthMeasureSpec, 0, NO_POSITION, heightSize, -1);

}

setMeasuredDimension(widthSize, heightSize);

mWidthMeasureSpec=widthMeasureSpec;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值