ActivityでViewの幅を正しく取得する方法


「Android開発芸術探索」の学習ノートです.
開発では、Activityであるviewの幅を取得する必要がある場合があり、ライフサイクルメソッドでgetWidth、getHeightを直接使用する場合、この2つのメソッドは実際には幅が広くないので、最後に取得した値はいずれも0であることがわかります.
では、これはなぜですか.これは、ViewのmeasureプロシージャとActivityのライフサイクルメソッドが同期して実行されないため、ActivityがonCreate、onStart、onResumeを実行したときにあるViewが測定済みであることを保証することはできません.Viewが測定済みでない場合、得られる幅は0です.
では、この問題をどのように解決するのでしょうか.ここには3つの方法があります.
1,Activity/ViewのonWindowFocusChanged
onWindowFocusChangedという方法の意味は、Viewが初期化され、アスペクトが準備されているので、このときアスペクトを取得するのは問題ありません.注意が必要なのは、onWindowFocusChangedが複数回呼び出され、Activityのウィンドウがフォーカスを取得し、フォーカスを失った場合に1回呼び出されます.
@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus) {
        int width = view.getMeasuredWith();
        int height = view.getMeasuredHeight();
    }
}

2, view.post(runnable)
postでrunnableをメッセージキューの末尾に送信し、Looperがrunnableを呼び出すのを待つと、Viewも初期化されます.
@Override
protected void onStart() {
    super.onStart();
    view.post(new Runnable() {
        @Override
        public void run() {
            int width = view.getMeasuredWidth();
            int height = view.getMeasuredHeight();
        }
    });
}

3, ViewTreeObserver
ViewTreeObserverの多くのコールバックインタフェースを使用することもできます.例えば、OnGlobalLayoutListenerというインタフェースを使用すると、Viewツリーの状態が変化したり、Viewツリー内部のViewの可視性が変化したりすると、onGlobalLayoutメソッドがコールバックされるので、Viewの幅の高さを取得する良い機会です.注目すべきは、ビューツリーの状態変化などに伴ってonGlobalLayoutが複数回呼び出されることです.
@Override
protected void onStart() {
    super.onStart();
    ViewTreeObserver observer = tv.getViewTreeObserver();
    observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            tv.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            int width = tv.getMeasuredWidth();
            int height = tv.getMeasuredHeight();
        }
    });
}

実は第4の方法がありますが、使うのは複雑で、ここでは言わないで、それからネット上で何年か前のブログの中でもどのようにviewの幅を持つかを書いていますが、それらのブログの中で書く方法は実は問題があって、ここでもあまり言いません.間違った方法は気にしないで、正しいことだけ覚えておけばいいのに、へへ!