总结一下自定义view:
1.执行顺序
onMeasure()——-onLayout()——onDraw();
注意:onLayout()一般 自定义view 中 可以不写,因为:我们在布局中可以直接定义位置
2.onMeasure()方法中的两个参数
前两位是测量模式,后两位是测量的值
模式分为:
1.UNSPECIFIED:父容器没有对当前View有任何限制,当前View可以任意取尺寸
2.EXACTLY:当前的尺寸就是当前View应该取的尺寸 。 对应的是我们布局中的 match_layout 或者 是 直接给的准确值 如:150dp
3.AT_MOST:当前尺寸是当前View能取的最大尺寸 。 对应的是我们布局中的 wrap_cantent
我们默认的的模式是EXACTLY
我们可以通过3种方式 给onMeasure 方法设置 你需要展示的宽高 ,这三种方式 分别对应不同的情况。
第一种
用户在布局中写什么,我们根据判断来获取
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = switch_background.getWidth();
if (specMode == MeasureSpec.AT_MOST) {
// Respect AT_MOST value if that was what is called for by
// measureSpec
result = Math.min(result, specSize);
}
}
return result;
}
最后在:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//通过判断把传入的值设置进去 setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec));
}
第二种:
直接调用setMeasuredDimension(),把我们需要让他多宽多高设置进去,这里设置之后。无论在xml里面 怎么规定,都不会影响 你通过该方法设置的宽高
setMeasuredDimension(switch_background.getWidth(),switch_background.getHeight());
第三种:
写一个方法,让调用者来设置:
1.直接传入值,不需要通过第一种方式来判断
setMeasuredDimension(widthMeasureSpec,heightMeasureSpec);
2.然后我们通过向外提供方法来控制
public void setWandH(int with,int height){
ViewGroup.LayoutParams params = getLayoutParams();
params.width=with;
params.height=height;
setLayoutParams(params);
}
执行完之后 会自动回调onMeasure()
3.关于getWith() 和getMearsureWith()区别:
简单来说getWith() 是我们能看见的高度,getMearsureWith()是空间实际的高度。
举个例子:
我手机屏幕宽200, 这是我有个控件宽是300,那么getwith 获取的值就是200, getMearsureWith 获取的值就是300
注意一点:getWith()只能在onlayout()方法执的执行完之后 才能获取,getMearsureWith() 在onMeasure()的setMeasuredDimension执行完之后就能获取。 在activity 中,onMearsure(),方法在onResurm()方法之后才执行,也就是说onResurm()之前包括onResurm()是无法获取 控件的宽高的。
如果想获取怎么办: 如下3个方法可以获取到
1. 在 onWindowFocusChanged 可以得到
2.
mTv.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
System.out.println("onGlobalLayout: "+mTv.getHeight());
mTv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
3.
mTv.post(new Runnable() {
@Override
public void run() {
System.out.println("run: "+mTv.getHeight());
}
});