2016年5月8日 星期日

獲取 View 的layout, 用OnGlobalLayoutListener , OnLayoutChangeListener ,view.post(new Runnable()

有時需要獲取某個 View 的layout, 或寬度,高度. 但如果太早呼叫只會得到null

因此通常會有以下三種方法
1.使用 ViewTreeObserver. OnGlobalLayoutListener 監聽事件:
在layout發生改變前加入該事件,會被多次呼叫,因此在獲取到layout後 remove 該事件。

view.getViewTreeObserver()
    .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {
            view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            view.getWidth(); // 獲取寬度
            view.getHeight(); // 獲取高度
        }
    });
}
2. View.OnLayoutChangeListener 監聽事件(API >= 11):
在layout發生改變前加入該事件,會被多次呼叫,因此在獲取到layout後 remove 該事件。
(用之前add,用完立即remove, 以免監聽到不必要的變動)

view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {

    @Override
    public void onLayoutChange(View v, int left, int top, int right, int bottom,
            int oldLeft, int oldTop, int oldRight, int oldBottom) {
        view.removeOnLayoutChangeListener(this);
        view.getWidth(); // 獲取寬度
        view.getHeight(); // 獲取高度
     }
});

3.使用 View.post() 方法:
Runnable 對象中的方法會在 View 的 measure、layout 等事件完成後觸發。
UI 事件隊列會按順序處理事件,在 setContentView() 被調用後,事件隊列中會包含一個要求重新 layout 的 message,所以任何 post 到隊列中的 Runnable 對象都會在 Layout 發生變化後執行。
該方法只會執行一次,且邏輯簡單,建議使用。

view.post(new Runnable() {

    @Override
    public void run() {
        view.getWidth(); // 獲取寬度
        view.getHeight(); // 獲取高度
    }
});

以上參考:

[Android] 獲取View的寬度和高度


以上第一個方法我使用時,有時也會得到null值
第二個方法沒用過
第三個方法, 實際我使用view.post時, 有時還會得到null值, 改用postDelayed的方法來延遲時間, 好像更好

tvDoc.postDelayed(new Runnable() {
    @Override    public void run() {
        // TODO Auto-generated method stub        Layout layout = tvDoc.getLayout();

        int a = layout.getLineForOffset(sbBe.abl[sbBe.curHit]);
        int y = layout.getLineTop(a); // e.g. I want to scroll to line        // 40        y = Math.max(0, y - 50);
        sv.smoothScrollTo(0, y);
    }
}, 100);//延遲100微秒

  © Blogger templates Psi by Ourblogtemplates.com 2008

Back to TOP