解決在onCreate()過程中擷取View的width和Height為0的4種方法__Java/Android

來源:互聯網
上載者:User

很經常當我們動態建立某些View時,需要通過擷取他們的width和height來確定別的view的布局,但是在onCreate()擷取view的width和height會得到0.view.getWidth()和view.getHeight()為0的根本原因是控制項還沒有完成繪製,你必須等待系統將繪製完View時,才能獲得。這種情況當你需要使用動態布局(使用wrap_content或match_parent)就會出現。一般來講在Activity.onCreate(...)、onResume()方法中都沒有辦法擷取到View的實際寬高。所以,我們必須用一種變通的方法,等到View繪製完成後去擷取width和Height。下面有一些可行的解決方案。 1、監聽Draw/Layout事件:ViewTreeObserver

ViewTreeObserver監聽很多不同的介面繪製事件。一般來說OnGlobalLayoutListener就是可以讓我們獲得到view的width和height的地方.下面onGlobalLayout內的代碼會在View完成Layout過程後調用。

 1 view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 2         @Override 3         public void onGlobalLayout() { 4             mScrollView.post(new Runnable() { 5                 public void run() { 6                     view.getHeight(); //height is ready 7                 } 8             }); 9         }10 });

但是要注意這個方法在每次有些view的Layout發生變化的時候被調用(比如某個View被設定為Invisible),所以在得到你想要的寬高後,記得移除onGlobleLayoutListener:

在 SDK Lvl < 16時使用
public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim)

在 SDK Lvl >= 16時使用
public void removeOnGlobalLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim) 2、將一個runnable添加到Layout隊列中:View.post()

這個解決方案是我最喜歡的,但是幾乎沒人知道有這個方法。簡單地說,只要用View.post()一個runnable就可以了。runnable對象中的方法會在View的measure、layout等事件後觸發,具體的參考Romain Guy:

UI事件隊列會按順序處理事件。在setContentView()被調用後,事件隊列中會包含一個要求重新layout的message,所以任何你post到隊列中的東西都會在Layout發生變化後執行。

1 final View view=//smth;2 ...3 view.post(new Runnable() {4             @Override5             public void run() {6                 view.getHeight(); //height is ready7             }8         });

這個方法比ViewTreeObserver好:
1、你的代碼只會執行一次,而且你不用在在每次執行後將Observer禁用,省心多了。
2、文法很簡單


參考:
http://stackoverflow.com/a/3602144/774398
http://stackoverflow.com/a/3948036/774398

  3、重寫View的onLayout方法

這個方法只在某些情境中實用,比如當你所要執行的東西應該作為他的內在邏輯被內聚、模組化在view中,否者這個解決方案就顯得十分冗長和笨重。

1 view = new View(this) {2     @Override3     protected void onLayout(boolean changed, int l, int t, int r, int b) {4         super.onLayout(changed, l, t, r, b);5         view.getHeight(); //height is ready6     }7 };

需要注意的是onLayout方法會調用很多次,所以要考慮好在這個方法中要做什麼,或者在第一次執行後禁用掉你的代碼。

  附加:擷取固定寬高

如果你要擷取的view的width和height是固定的,那麼你可以直接使用:

1 View.getMeasureWidth()2 View.getMeasureHeight()

但是要注意,這兩個方法所擷取的width和height可能跟實際draw後的不一樣。官方文檔解釋了不同的原因:

View的大小由width和height決定。一個View實際上同時有兩種width和height值。

第一種是measure width和measure height。他們定義了view想要在父View中佔用多少width和height(詳情見Layout)。measured height和width可以通過getMeasuredWidth() 和 getMeasuredHeight()獲得。

第二種是width和height,有時候也叫做drawing width和drawing height。這些值定義了view在螢幕上繪製和Layout完成後的實際大小。這些值有可能跟measure width和height不同。width和height可以通過getWidth()和getHeight獲得。

 

參考連結

https://stackoverflow.com/questions/3591784/getwidth-and-getheight-of-view-returns-0/24035591#24035591

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.