resolveSize(int size , int measureSpec);
这是一个自定义view获取size的神器,
首先我们来看下 我不知道这个方法之前获取size的写法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mStepCount = mSteps.size();
if (mStepCount == 0) {
setMeasuredDimension(0, 0);
} else {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY) {
mHeight = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
mHeight = Math.min(mCircleRadius * 2 + 8 + mTextSize, heightSize);
} else {
mHeight = heightSize;
}
int desireWidth = (mCircleRadius * mSteps.size() + mLineLength * (mSteps.size() - 1)) * 2;
if (widthMode == MeasureSpec.EXACTLY) {
if (desireWidth > widthSize) {
float v = desireWidth * 1f / widthSize;
mCircleRadius = (int) (mCircleRadius * 1f / v);
mLineLength = (int) (mLineLength * 1f / v);
}
mWidth = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
if (desireWidth > mScreenWidth) {
float v = desireWidth * 1f / mScreenWidth;
mCircleRadius = (int) (mCircleRadius * 1f / v);
mLineLength = (int) (mLineLength * 1f / v);
desireWidth = (mCircleRadius * mSteps.size() + mLineLength * (mSteps.size() - 1)) * 2;
}
mWidth = Math.min(desireWidth, widthSize);
} else {
mWidth = widthSize;
}
setMeasuredDimension(mWidth, mHeight);
}
}
整整40行,而通过这个方法后获得的
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //对于desireSize,只是我为了讲解,只是临时写的一个初始值,大家要自己根据需要计算
int desireWidthSize = 0;
int width =resolveSize(desireWidthSize, widthMeasureSpec);
int desireHeightSize= 0;
int height = resolveSize(desireHeightSize, heightMeasureSpec);
setMeasuredDimension(width, height);
}
只要8行 有没有很吊,有没有很吊,很简单,缩短了整整5倍,当然这个方法我不推荐初学者立马就使用,而是希望初学者能够多写写我写的那种,这样子能够更深刻的明白onmeasure这个方法的使用,以及如何实现,
那么接下来就来说下这个方法,其实这方法也是挺简单的 接受两个参数,size,measureSpec,
首先第一个参数的意思你希望你的view有多大,第二个参数的就是测量的measureSpec,
通过查看这个方法的源码
/**
* Version of {@link #resolveSizeAndState(int, int, int)}
* returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
*/
public static int resolveSize(int size, int measureSpec) {
return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
}
是这个,然后继续看
/**
* Utility to reconcile a desired size and state, with constraints imposed
* by a MeasureSpec. Will take the desired size, unless a different size
* is imposed by the constraints. The returned value is a compound integer,
* with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
* optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
* resulting size is smaller than the size the view wants to be.
*
* @param size How big the view wants to be.
* @param measureSpec Constraints imposed by the parent.
* @param childMeasuredState Size information bit mask for the view's
* children.
* @return Size information bit mask as defined by
* {@link #MEASURED_SIZE_MASK} and
* {@link #MEASURED_STATE_TOO_SMALL}.
*/
public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
final int specMode = MeasureSpec.getMode(measureSpec);
final int specSize = MeasureSpec.getSize(measureSpec); //获取size,mode
final int result;
switch (specMode) {
case MeasureSpec.AT_MOST://如果是AT_MOST
if (specSize < size) { //,测量出来的size<你需要的size,那么他就会告诉你 测量出的来的size过小
result = specSize | MEASURED_STATE_TOO_SMALL;
} else {
result = size; //否则的话 就返回你需要的size
}
break;
case MeasureSpec.EXACTLY:
result = specSize; //对于是EXACTLY,你测出来多大 ,就返回多大
break;
case MeasureSpec.UNSPECIFIED:
default:
result = size; //至于是UNSPECIFIED,那就返回你需要的size
}
return result | (childMeasuredState & MEASURED_STATE_MASK);
}
耐心的仔细读下来,就会发现,其实他就是做了帮你测量步骤,具体请看我后面的注释
google帮你写好了步骤,这样会使你的代码更加整洁,代码量还少。