获取View组件宽度以及ViewTreeObserver
View宽高测量方法:
测量方法有三种,如下:
1)(直接在onCreate()执行)
int w = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED); int h = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED); imageView.measure(w, h); int height =imageView.getMeasuredHeight(); int width =imageView.getMeasuredWidth(); textView.append("\n"+height+","+width);
2)2和3都是在onCreate()调用完后回调拿到组件的宽高
ViewTreeObserver vto = imageView.getViewTreeObserver(); vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { public boolean onPreDraw() { int height = imageView.getMeasuredHeight(); int width = imageView.getMeasuredWidth(); textView.append("\n"+height+","+width); return true; } });
3)
ViewTreeObserver vto2 = imageView.getViewTreeObserver(); vto2.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this); textView.append("\n\n"+imageView.getHeight()+","+imageView.getWidth()); } });
注意:方法一比其他方法多一次onMeasure计算,方法二的回调函数会被多次调用。
转自http://blog.csdn.net/johnny901114/article/details/7839512
ViewTreeObserver
一、结构
public final class ViewTreeObserver extends Object java.lang.Object android.view.ViewTreeObserver
二、概述
这是一个注册监听视图树的观察者(observer),在视图树种全局事件改变时得到通知。这个全局事件不仅还包括整个树的布局,从绘画过程开始,触摸模式的改变等。ViewTreeObserver不能够被应用程序实例化,因为它是由视图提供,参照getViewTreeObserver()以查看更多信息。
三、内部类
interface ViewTreeObserver.OnGlobalFocusChangeListener //当在一个视图树中的焦点状态发生改变时,所要调用的回调函数的接口类 interface ViewTreeObserver.OnGlobalLayoutListener //当在一个视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变时,所要调用的回调函数的接口类 interface ViewTreeObserver.OnPreDrawListener //当一个视图树将要绘制时,所要调用的回调函数的接口类 interface ViewTreeObserver.OnScrollChangedListener //当一个视图树中的一些组件发生滚动时,所要调用的回调函数的接口类 interface ViewTreeObserver.OnTouchModeChangeListener //当一个视图树的触摸模式发生改变时,所要调用的回调函数的接口类
四、公共方法
/**注册一个回调函数,当在一个视图树中的焦点状态发生改变时调用这个回调函数。 * 参数 listener 将要被添加的回调函数 *异常 IllegalStateException 如果isAlive() 返回false */ public void addOnGlobalFocusChangeListener (ViewTreeObserver.OnGlobalFocusChangeListener listener) /**注册一个回调函数,当在一个视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变时调用这个回调函数。 *参数 listener 将要被添加的回调函数 *异常 IllegalStateException 如果isAlive() 返回false */ public void addOnGlobalLayoutListener (ViewTreeObserver.OnGlobalLayoutListener listener) /**注册一个回调函数,当一个视图树将要绘制时调用这个回调函数。 *参数 listener 将要被添加的回调函数 *异常 IllegalStateException 如果isAlive() 返回false */ public void addOnPreDrawListener (ViewTreeObserver.OnPreDrawListener listener) /**注册一个回调函数,当一个视图发生滚动时调用这个回调函数。 *参数 listener 将要被添加的回调函数 *异常 IllegalStateException 如果isAlive() 返回false */ public void addOnScrollChangedListener (ViewTreeObserver.OnScrollChangedListener listener) /**注册一个回调函数,当一个触摸模式发生改变时调用这个回调函数。 *参数 listener 将要被添加的回调函数 *异常 IllegalStateException 如果isAlive() 返回false */ public void addOnTouchModeChangeListener (ViewTreeObserver.OnTouchModeChangeListener listener) //当整个布局发生改变时通知相应的注册监听器。如果你强制对视图布局或者在一个没有附加到一个窗口的视图的层次结构或者在GONE状态下,它可以被手动的调用 public final void dispatchOnGlobalLayout () /**当一个视图树将要绘制时通知相应的注册监听器。如果这个监听器返回true,则这个绘制将被取消并重新计划。如果你强制对视图布局或者在一个没有附加到一个窗口的视图的层次结构或者在一个GONE状态下,它可以被手动的调用 *返回值 当前绘制能够取消并重新计划则返回true,否则返回false。 */ public final boolean dispatchOnPreDraw () /**指示当前的ViewTreeObserver是否可用(alive)。当observer不可用时,任何方法的调用(除了这个方法)都将抛出一个异常。如果一个应用程序保持和ViewTreeObserver一个历时较长的引用,它应该总是需要在调用别的方法之前去检测这个方法的返回值。 *返回值 但这个对象可用则返回true,否则返回false */ public boolean isAlive () /**移除之前已经注册的全局布局回调函数。 *参数 victim 将要被移除的回调函数 *异常 IllegalStateException 如果isAlive() 返回false */ public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim) /**移除之前已经注册的焦点改变回调函数。 *参数 victim 将要被移除的回调函数 *异常 IllegalStateException 如果isAlive() 返回false */ public void removeOnGlobalFocusChangeListener (ViewTreeObserver.OnGlobalFocusChangeListener victim) /**移除之前已经注册的预绘制回调函数。 *参数 victim 将要被移除的回调函数 *异常 IllegalStateException 如果isAlive() 返回false */ public void removeOnPreDrawListener (ViewTreeObserver.OnPreDrawListener victim) /**移除之前已经注册的滚动改变回调函数。 *参数 victim 将要被移除的回调函数 *异常 IllegalStateException 如果isAlive() 返回false */ public void removeOnScrollChangedListener (ViewTreeObserver.OnScrollChangedListener victim) /**移除之前已经注册的触摸模式改变回调函数 *参数 victim 将要被移除的回调函数 *异常 IllegalStateException 如果isAlive() 返回false */ public void removeOnTouchModeChangeListener (ViewTreeObserver.OnTouchModeChangeListener victim)
五、代码示例
1、创建监听器
private final ViewTreeObserver.OnGlobalLayoutListener mGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int width = -1; int height = -1; try { width = getActivity().getWindow().getDecorView().getWidth(); height = getActivity().getWindow().getDecorView().getHeight(); } catch (Exception e) { // called too early. so, just skip. } if (width != -1 && mGlobalLayoutWidth != width) {//只有当尺寸真正有了数值,即已经确定了,更新UI才有意义 mGlobalLayoutWidth = width; updateUI(); } else if (height != -1 && mGlobalLayoutHeight != height) { mGlobalLayoutHeight = height; updateUI(); } } };
2、一般在onCreate或onCreateView中注册监听器
mViewTreeObserver = getActivity().getWindow().getDecorView().getViewTreeObserver();
mViewTreeObserver.addOnGlobalLayoutListener(mGlobalLayoutListener);