View寬高測量方法: 測量方法有三種,如下: 1)(直接在onCreate()執行) 2)2和3都是在onCreate()調用完後回調拿到組件的寬高 3) 註意:方法一比其他方法多一次onMeasure計算,方法二的回調函數會被多次調用。 轉自http://blog.csdn.net/johnny ...
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);