Android擷取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計算,方法二的回呼函數會被多次調用。
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);
https://www.bkjia.com/topicnews.aspx?tid=5
本文永久更新連結地址:https://www.bkjia.com/Linux/2018-02/151003.htm