Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android: 在onCreate()中獲得對象尺寸

Android: 在onCreate()中獲得對象尺寸

編輯:關於Android編程

onCreate() 中 View 尚未繪制完成 很多時候,我們需要在某個界面剛剛加載的時候,執行一些對 View 進行操作的代碼,通常我們把這些代碼放在 Activity 的 onCreate() 方法或 Fragment 的 onCreateView() 方法中。但因為在這些 Hook 方法被調用時,View 並沒有繪制完成,很多操作不能生效。   比如,在 onCreate() 中調用某個按鈕的 myButton.getHeight(),得到的結果永遠是0。不想花時間慢慢看的同學,可以直接去看最後結論中的解決方案。   Button myButton = null;   @Override protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_welcome);     myButton = (Button) findViewById(R.id.button1);          // 嘗試在 onCreate() 中獲取控件尺寸     int h = myButton.getHeight();     Log.i(TAG, "onCreate(): Height=" + h);  // 得到當結果是 Height=0          // ... } 類似的情況還有很多,筆者之前自己寫了一個下拉刷新的 ListView,希望在 Fragment 完成繪制後,立刻執行一次刷新,並將代碼寫在了 onCreateView() 中。結果是,列表確實進行了刷新操作,但是沒有下拉刷新的動畫。   更晚調用的生命周期函數 筆者開始以為,既然 onCreate() 中,控件尚未繪制完成,那麼將代碼寫在更晚執行的一些生命周期函數中,問題是不是能得到解決呢?之後筆者分別在 Actvity 中的一些常用的 Hook 函數中,嘗試獲取控件的尺寸,得到如下結果(按被執行的順序排列):   onCreate(): Height=0 onStart(): Height=0 onPostCreate(): Height=0 onResume(): Height=0 onPostResume(): Height=0 onAttachedToWindow(): Height=0 onWindowsFocusChanged(): Height=1845 可以看到,直到 onWinodwsFocusChanged() 函數被調用,我們才能得到正確的控件尺寸。其他 Hook 函數,包括在官方文檔中,描述為在 Activity 完全啟動後才調用的 onPostCreate() 和 onPostResume() 函數,均不能得到正確的結果。   遺憾的是,雖然在 onWinodwsFocusChanged() 函數中,可以得到正確的控件尺寸。但這只在 Activity 中奏效,而在 Fragment 中,該方法並不能生效。   更多的解決方案 1. 使用 ViewTreeObserver 提供的 Hook 方法。 @Override protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_welcome);     myButton = (Button) findViewById(R.id.button1);          // 向 ViewTreeObserver 注冊方法,以獲取控件尺寸     ViewTreeObserver vto = myButton.getViewTreeObserver();     vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {         public void onGlobalLayout() {             int h = myButton.getHeight();             Log.i(TAG, "Height=" + h); // 得到正確結果               // 成功調用一次後,移除 Hook 方法,防止被反復調用             // removeGlobalOnLayoutListener() 方法在 API 16 後不再使用             // 使用新方法 removeOnGlobalLayoutListener() 代替             myButton.getViewTreeObserver().removeGlobalOnLayoutListener(this);         }     });          // ... } 該方法在 onGlobalLayout() 方法將在控件完成繪制後調用,因而可以得到正確地結果。該方法在 Fragment 中,也可以使用。   2. 使用 View 的 post() 方法 @Override protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_welcome);     myButton = (Button) findViewById(R.id.button1);          // 使用myButton 的 post() 方法     myButton.post(new Runnable() {         @Override         public void run() {             int h = myButton.getHeight();             Log.i(TAG, "Height=" + h); // 得到正確結果         }     });          // ... } 該方法同樣在 Fragment 中適用,是目前筆者發現的最佳解決方案。   注意:通過調用測量對象的 post() 方法注冊的 Runnable 總在對象完全繪制後才調用,所以可以得到正確的結果。但直接在 onCreate() 中,使用 new Handler().post(mRunnabel) 並不能得到正確的結果。   很多教程中,通過延遲一個毫秒數,即 new Handler().postDelayed(mRunnabel, 500),來調用執行實際測量工作的 Runnable。這樣雖然能得到正確的結果,但顯然不是一個好的解決方案:太小的毫秒數不能保證控件完成繪制,太大的毫秒數,會嚴重破壞用戶的操作體驗。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved