概述
如何获取view的宽/高度?许多人都会用getWidth()或者getMeasuredWidth(),但是这两者有什么不一样呢?
View的绘制过程是measure->layout->draw。看下measure的代码:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
public static int getDefaultSize(int size, int measureSpec) {
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
result = size;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
看下getDefaultSize函数,这个函数测量到的大小是根据父容器的measureSpec同时结合view本身的layoutparams来确定子元素的measureSpec。这时计算出的大小是getMeasuredWidth(),但是view最终的大小是在layout阶段确定的(用getWidth()读取),所以这里要加以区分,但是几乎所有情况下view的测量和最终大小是相等的。所以一个比较好的习惯是在onLayout函数中去获取view的大小。
如果在一个activity启动的时候,想要去获取某个view的宽高,是不可以在onCreate或者onResume等生命周期函数中去取,这是因为view的绘制和activity的生命周期是异步的,所以在这些生命周期函数中去绘制的话,会导致获取到的宽度为0。下面介绍几种方法来获取:
- 通过onWindowFocusChanged,这个方法的含义是:view已经初始化完毕了,宽高已经准备好了,这个时候去获取宽高是没问题的。当Activity的窗口获取焦点或失去焦点均会被调用,太频繁,这样不好。
- view.post(runnable):通过post可以将一个runnable投递到消息队列的尾部,然后等looper调用此runnable的时候,view也已经初始化好了。典型代码:
protected void onStart(){
super.onStart();
view.post(new Runnable(){
@Override
public void run(){
int width = view.getWidth();
int height = view.getHeight();
}
});
}
- ViewTreeObserver:使用ViewTreeObserver的众多回调可以完成这个功能,比如使用onGlobalLayoutListener这个接口,当view树的状体发生改变或view树内部的view的可见性发生改变时,onGlobalLayout方法将被回调,因此这是一个获取view宽高很好的机会。需要注意的是,随着view树的变化,该回调将会被调用多次,获取宽高后需要remove该Listener。
void func(final View view){
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int width = view.getWidth();
int height = view.getHeight();
}
});
}
MeasureSpec.UNSPECIFIED这种情况,一般用于系统内部的测量过程,getDefaultSize传入的specSize分别为getSuggestedMinimumWidth()和getSuggestedMinimumHeight()。
protected int getSuggestedMinimumWidth() {
return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
}
protected int getSuggestedMinimumHeight() {
return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
}
如果这个view没有设置背景,那么返回的是mMinWidth或者mMinHeight,这两个值对应的是android:minWidth和android:minHeight,但是如果设置了background,就取background.getMinimumHeight和mMinHeight的大值。
那Drawable的getMinimumHeight()函数返回的是什么呢?
public int getMinimumHeight() {
final int intrinsicHeight = getIntrinsicHeight();
return intrinsicHeight > 0 ? intrinsicHeight : 0;
}
可以看出getMinimumHeight返回的就是drawable的原始高度。如果是BitmapDrawable的话,返回bitmap的原始高度,如果是ShapeDrawable无原始高度,返回0。
最后
以上就是悲凉荷花为你收集整理的getMeasuredWidth()和getWidth()的全部内容,希望文章能够帮你解决getMeasuredWidth()和getWidth()所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复