
问题:我们的Activity中有一张上面的图片ImageView,现在想测量一下,这个ImageView的宽高尺寸,我们该怎么做呢?
我们要测量一个View的尺寸,那么肯定要在这个View夹在完成之后。由于View的measure过程和Activity的生命周期不是同步执行的,所以在Activity的 onCreate
, onStart
, onResume
生命周期的回调中,我们是无法获取到一个View的准确宽高尺寸的。
那么,我们想要准确的得到一个View的尺寸大小就得用其他的方法了
准确的在Activity中测量一个View的宽高尺寸
- Activity / View #
onWindowFocusChanged
onWindowFocusChanged
此时View已经初始化完毕,当Activity的窗口得到焦点 和失去焦点时均会被调用一次,如果频繁地进行onResume
和onPause
,那么onWindowFocusChanged
也会被频繁地调用。
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
// 获取View的宽高
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
}
- view.post(runnable)
通过post
可以将一个runnable
投递到消息队列的尾部,始化好了然后等待Looper
调用次runnable
的时候,View也已经初始化好了。
@Override
protected void onStart() {
super.onStart();
view.post(new Runnable() {
@Override
public void run() {
// 获取View的宽高
int width = mTextView.getMeasuredWidth();
int height = mTextView.getMeasuredHeight();
}
});
}
- ViewTreeObserver#
addOnGlobalLayoutListener
当View树的状态发生改变或者View树内部的 View的可见性发生改变时,onGlobalLayout方法将被回调。因此这是获取View的宽高的一个很好的时机,需要注意:伴随View树状态的改变,这个方法也会被调用多次
@Override
protected void onStart() {
super.onStart();
ViewTreeObserver observer = view.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// 获取View的宽高
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
});
}
- view.measure(int widthMeasureSpec , int heightMeasureSpec)
通过手动测量View的宽高,需要根据View的LayoutParams
来分不同情况处理
1,match_parent
无法测量出具体的宽高,根据View的测量过程,构造这种measureSpec
需要知道parentSize
,即父容器的剩下空间,而这个时候我们无法知道parentSize
的大小,所以理论上我们不可能测量出View的大小
2,具体的数值
直接makeMeasureSpec固定值,然后调用 view..measure就可以了
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY);
view.measure(widthMeasureSpec,heightMeasureSpec);
3, wrap_content
在最大化模式下,用View理论上能支持的最大值去 构造MeasureSpec是合理的。
int widthMeasureSpec = MeasureSpec.makeMeasureSpec((1<<30)-1, MeasureSpec.AT_MOST);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec((1<<30)-1, MeasureSpec.AT_MOST);
view.measure(widthMeasureSpec,heightMeasureSpec);
关于View测量的一个工具类
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
/**
*
* 描述: 布局参数设置工具类
*
**/
public class LayoutParamerUtils {
/**
*
* 描述: 获取 指定view 的 viewTreeObserver
* created: 2018/6/14/014 18:49
*
**/
public static void getViewObserver(final View viewtest, final ViewObserverListener viewObserverListener) {
if(viewtest == null){
return;
}
viewtest.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener(){
@Override
public void onGlobalLayout() {
viewtest.getViewTreeObserver().removeOnGlobalLayoutListener(this);
if(viewObserverListener != null){
viewObserverListener.onViewObserverResult();
}
}
});
}
/**
*
* 描述: getViewObserver 回调接口
* created: 2018/6/14/014 18:54
*
**/
public interface ViewObserverListener{
void onViewObserverResult();
}
}
网友评论