Activity正確獲取View寬高
阿新 • • 發佈:2018-11-01
在View的measure完成後,一般可以通過getMeasureWidth/getMeasureWidth方法可以正確的獲取View的寬高,而在特殊情況下,可能需要多次measure才能確定最終的測量寬高,onMeasure無法獲取正確的寬高,但可以在onLayout方法中獲取測量寬高。
而在Activity生命週期方法中,是無法通過getMeasureWidth/getMeasureWidth獲取正確的測量寬高,是因為View的measure和Activity的生命週期方法不是同步執行的,因此無法保證Activity執行生命週期方法時View已經繪製完畢,如果沒有繪製完,寬高可能是0。可以通過以下四種方法解決這個問題:
1、Acvtivity/View#onWindowFocusChanged
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
}
需要注意的是,這個方法可能會被呼叫多次,例如onResume和onPause呼叫,均會呼叫這個方法。
2、view.post(runnable)
通過post可以將一個runnable投遞到訊息佇列的尾部,等待Looper呼叫次runnable時候,view已經初始化了。
view.post(new Runnable() {
@Override
public void run() {
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
});
3、ViewTreeObserver
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { view.getViewTreeObserver().removeOnGlobalLayoutListener(this::onGlobalLayout); int width = view.getMeasuredWidth(); int height = view.getMeasuredHeight(); } });
需要注意,伴隨著View樹的狀態改變,onGlobalLayout()會被呼叫多次。
4、view.measure(int widthMeasureSpec,int heightMeasureSpec)
通過手動對View進行measure來得到View的寬高,但需要根據不同情況來進行處理
- match_parent
這個無法measure具體的寬高,是因為需要知道父容器的parentSize,但這個時候是無法獲取的。
- 具體的數值
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY);
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY);
view.measure(widthMeasureSpec, heightMeasureSpec);
- wrap_content
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec((1 << 30) - 1, View.MeasureSpec.AT_MOST);
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec((1 << 30) - 1, View.MeasureSpec.AT_MOST);
view.measure(widthMeasureSpec, heightMeasureSpec);