首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 取得 View 寬高為 0 問題根因與 ViewTreeObserver 解決方案

     編輯:程式設計綜合問答

在 onCreate、onStart、onResume 中直接呼叫 view.getWidth()/getHeight() 回傳 0,因視圖尚未經歷 Measure → Layout → Draw 三階段,尺寸尚未計算完成。正解為使用 ViewTreeObserver.OnGlobalLayoutListener 監聽佈局完成事件。

錯誤示範


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    TableLayout table = findViewById(R.id.board);
    int w = table.getWidth();  // 0
    int h = table.getHeight(); // 0
}

標準解決方案:OnGlobalLayoutListener


final TableLayout table = findViewById(R.id.board);
ViewTreeObserver vto = table.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // 此時寬高已計算完成
        int width = table.getWidth();
        int height = table.getHeight();
        Log.d("Size", "Table: " + width + "x" + height);
        
        // 重要:移除監聽器避免重複觸發與記憶體洩漏
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            table.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        } else {
            table.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        }
        
        // 執行需要尺寸的邏輯...
    }
});

替代方案比較

方案觸發時機優點缺點
OnGlobalLayoutListener佈局完成、尺寸確定最準確、通用需記得移除監聽器
view.post(Runnable)下一幀 UI 執行緒代碼簡單不保證佈局已完成(極簡單佈局通常夠)
onWindowFocusChanged視窗獲得焦點確保可見可能觸發多次、非專門為尺寸
doOnLayout / doOnNextLayout (Kotlin Extensions)佈局完成語法簡潔、自動移除需引入 ktx 依賴

Kotlin 擴充函數簡化寫法


// build.gradle: implementation "androidx.core:core-ktx:1.12.0"

table.doOnLayout { view ->
    val width = view.width
    val height = view.height
    // 尺寸就緒,執行邏輯
}

常見應用場景

  • 動態計算 TextView 行數、截斷位置
  • 自訂 View 依賴尺寸初始化繪圖參數
  • 啟動動畫前需知終點座標
  • 截圖/生成 Bitmap 需實際像素尺寸

注意事項

  • 監聽器中若修改佈局參數可能觸發再次佈局,導致無限迴圈 → 僅讀取尺寸或使用標記位控制。
  • RecyclerView、ViewPager 子項尺寸在 Adapter 綁定後才確定,需在 onBindViewHolder 或 OnGlobalLayoutListener 中處理。
  • Fragment 中使用 viewLifecycleOwner 綁定生命週期,避免洩漏。

理解 Android 視圖繪製管線,善用 ViewTreeObserver,即能準確獲取任意視圖的實際尺寸。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved