日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android获得一个view的高度,Android ViewTreeObserver使用总结及获得View高度的几种方法...

發布時間:2023/12/20 Android 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android获得一个view的高度,Android ViewTreeObserver使用总结及获得View高度的几种方法... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

ViewTreeObserver 注冊一個觀察者來監聽視圖樹,當視圖樹的布局、視圖樹的焦點、視圖樹將要繪制、視圖樹滾動等發生改變時,ViewTreeObserver都會收到通知,ViewTreeObserver不能被實例化,可以調用View.getViewTreeObserver()來獲得。

ViewTreeObserver繼承關系:

public final class ViewTreeObserverextendsObject

java.lang.Object

?android.view.ViewTreeObserver

ViewTreeObserver直接繼承自Object.

ViewTreeObserver提供了View的多種監聽,每一種監聽都有一個內部類接口與之對應,內部類接口全部保存在CopyOnWriteArrayList中,通過ViewTreeObserver.addXXXListener()來添加這些監聽,源碼如下:

public final class ViewTreeObserver {

// Recursive listeners use CopyOnWriteArrayList

private CopyOnWriteArrayList mOnWindowFocusListeners;

private CopyOnWriteArrayList mOnWindowAttachListeners;

private CopyOnWriteArrayList mOnGlobalFocusListeners;

private CopyOnWriteArrayList mOnTouchModeChangeListeners;

private CopyOnWriteArrayList mOnEnterAnimationCompleteListeners;

// Non-recursive listeners use CopyOnWriteArray

// Any listener invoked from ViewRootImpl.performTraversals() should not be recursive

private CopyOnWriteArray mOnGlobalLayoutListeners;

private CopyOnWriteArray mOnComputeInternalInsetsListeners;

private CopyOnWriteArray mOnScrollChangedListeners;

private CopyOnWriteArray mOnPreDrawListeners;

private CopyOnWriteArray mOnWindowShownListeners;

// These listeners cannot be mutated during dispatch

private ArrayList mOnDrawListeners;

}

以OnGlobalLayoutListener為例,首先是定義接口:

public interface OnGlobalLayoutListener {

/**

* Callback method to be invoked when the global layout state or the visibility of views

* within the view tree changes

*/

public void onGlobalLayout();

}

將OnGlobalLayoutListener 添加到CopyOnWriteArray數組中:

/**

* Register a callback to be invoked when the global layout state or the visibility of views

* within the view tree changes

*

* @param listener The callback to add

*

* @throws IllegalStateException If {@link #isAlive()} returns false

*/

public void addOnGlobalLayoutListener(OnGlobalLayoutListener listener) {

checkIsAlive();

if (mOnGlobalLayoutListeners == null) {

mOnGlobalLayoutListeners = new CopyOnWriteArray();

}

mOnGlobalLayoutListeners.add(listener);

}

移除OnGlobalLayoutListener,當視圖樹布局發生變化時不會再收到通知了:

/**

* Remove a previously installed global layout callback

*

* @param victim The callback to remove

*

* @throws IllegalStateException If {@link #isAlive()} returns false

*

* @deprecated Use #removeOnGlobalLayoutListener instead

*

* @see #addOnGlobalLayoutListener(OnGlobalLayoutListener)

*/

@Deprecated

public void removeGlobalOnLayoutListener(OnGlobalLayoutListener victim) {

removeOnGlobalLayoutListener(victim);

}

/**

* Remove a previously installed global layout callback

*

* @param victim The callback to remove

*

* @throws IllegalStateException If {@link #isAlive()} returns false

*

* @see #addOnGlobalLayoutListener(OnGlobalLayoutListener)

*/

public void removeOnGlobalLayoutListener(OnGlobalLayoutListener victim) {

checkIsAlive();

if (mOnGlobalLayoutListeners == null) {

return;

}

mOnGlobalLayoutListeners.remove(victim);

}

其他常用方法:

dispatchOnGlobalLayout():視圖樹發生改變時通知觀察者,如果想在View Layout 或 View hierarchy 還未依附到Window時,或者在View處于GONE狀態時強制布局,這個方法也可以手動調用。

/**

* Notifies registered listeners that a global layout happened. This can be called

* manually if you are forcing a layout on a View or a hierarchy of Views that are

* not attached to a Window or in the GONE state.

*/

public final void dispatchOnGlobalLayout() {

// NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to

// perform the dispatching. The iterator is a safe guard against listeners that

// could mutate the list by calling the various add/remove methods. This prevents

// the array from being modified while we iterate it.

final CopyOnWriteArray listeners = mOnGlobalLayoutListeners;

if (listeners != null && listeners.size() > 0) {

CopyOnWriteArray.Access access = listeners.start();

try {

int count = access.size();

for (int i = 0; i < count; i++) {

access.get(i).onGlobalLayout();

}

} finally {

listeners.end();

}

}

}

dispatchOnPreDraw():通知觀察者繪制即將開始,如果其中的某個觀察者返回 true,那么繪制將會取消,并且重新安排繪制,如果想在View Layout 或 View hierarchy 還未依附到Window時,或者在View處于GONE狀態時強制繪制,可以手動調用這個方法。

/**

* Notifies registered listeners that the drawing pass is about to start. If a

* listener returns true, then the drawing pass is canceled and rescheduled. This can

* be called manually if you are forcing the drawing on a View or a hierarchy of Views

* that are not attached to a Window or in the GONE state.

*

* @return True if the current draw should be canceled and resceduled, false otherwise.

*/

@SuppressWarnings("unchecked")

public final boolean dispatchOnPreDraw() {

boolean cancelDraw = false;

final CopyOnWriteArray listeners = mOnPreDrawListeners;

if (listeners != null && listeners.size() > 0) {

CopyOnWriteArray.Access access = listeners.start();

try {

int count = access.size();

for (int i = 0; i < count; i++) {

cancelDraw |= !(access.get(i).onPreDraw());

}

} finally {

listeners.end();

}

}

return cancelDraw;

}

ViewTreeObserver常用內部類:

內部類接口

備注

ViewTreeObserver.OnPreDrawListener

當視圖樹將要被繪制時,會調用的接口

ViewTreeObserver.OnGlobalLayoutListener

當視圖樹的布局發生改變或者View在視圖樹的可見狀態發生改變時會調用的接口

ViewTreeObserver.OnGlobalFocusChangeListener

當一個視圖樹的焦點狀態改變時,會調用的接口

ViewTreeObserver.OnScrollChangedListener

當視圖樹的一些組件發生滾動時會調用的接口

ViewTreeObserver.OnTouchModeChangeListener

當視圖樹的觸摸模式發生改變時,會調用的接口

獲得View高度的幾種方式:

我們應該都遇到過在onCreate()方法里面調用view.getWidth()和view.getHeight()獲取到的view的寬高都是0的情況,這是因為在onCreate()里還沒有執行測量,需要在onResume()之后才能得到正確的高度,那么可不可以在onCreate()里就得到寬高呢?答:可以!常用的有下面幾種方式:

1、通過設置View的MeasureSpec.UNSPECIFIED來測量:

int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);

int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);

view.measure(w, h);

//獲得寬高

int viewWidth=view.getMeasuredWidth();

int viewHeight=view.getMeasuredHeight();

設置我們的SpecMode為UNSPECIFIED,然后去調用onMeasure測量寬高,就可以得到寬高。

2、通過ViewTreeObserver .addOnGlobalLayoutListener來獲得寬高,當獲得正確的寬高后,請移除這個觀察者,否則回調會多次執行:

//獲得ViewTreeObserver

ViewTreeObserver observer=view.getViewTreeObserver();

//注冊觀察者,監聽變化

observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

@Override

public void onGlobalLayout() {

//判斷ViewTreeObserver 是否alive,如果存活的話移除這個觀察者

if(observer.isAlive()){

observer.removeGlobalOnLayoutListener(this);

//獲得寬高

int viewWidth=view.getMeasuredWidth();

int viewHeight=view.getMeasuredHeight();

}

}

});

3、通過ViewTreeObserver .addOnPreDrawListener來獲得寬高,在執行onDraw之前已經執行了onLayout()和onMeasure(),可以得到寬高了,當獲得正確的寬高后,請移除這個觀察者,否則回調會多次執行

//獲得ViewTreeObserver

ViewTreeObserver observer=view.getViewTreeObserver();

//注冊觀察者,監聽變化

observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

@Override

public boolean onPreDraw() {

if(observer.isAlive()){

observer.removeOnDrawListener(this);

}

//獲得寬高

int viewWidth=view.getMeasuredWidth();

int viewHeight=view.getMeasuredHeight();

return true;

}

});

總結

以上是生活随笔為你收集整理的android获得一个view的高度,Android ViewTreeObserver使用总结及获得View高度的几种方法...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。