1. 程式人生 > >獲取View組件寬度以及ViewTreeObserver

獲取View組件寬度以及ViewTreeObserver

listener urn () mod server spec style 改變 實例

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);

獲取View組件寬度以及ViewTreeObserver