獲取View的寬/高
在Activity的onCreate、onStart、onResume中均無法正確得到某個View的寬/高信息,這是因為View的measure過程和Activity的生命周期方法不是同步執(zhí)行的,因此無法保證Activity執(zhí)行了onCreate、onStart、onResume時某個View已經(jīng)測量完畢了,如果View還沒有測量完畢,那么獲得的寬/高就是0。可以通過以下幾種方法獲取。
一、Activity/View#onWindowFocusChanged
onWindowFocusChanged方法的含義是:View已經(jīng)初始化完畢,寬/高已經(jīng)準(zhǔn)備好了,這個時候去獲取寬/高是沒問題的。需要注意的是,當(dāng)Activity的窗口得到焦點和失去焦點時均會被調(diào)用一次。
pubic void onWinowFocusChanged(boolean hasFocus) {
super.onWinowFocusChanged(hasFocus);
if(hasFocus) {
int widht = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
}
二、view.post(runnable)
通過post可以將runnable投遞到消息隊列的尾部,然后等待Looper調(diào)用此runnable的時候,View也已經(jīng)初始化好了。
protected void onStart() {
super.onStart();
view.post(new Runnable() {
@Override
public void run() {
int width = view.getMeasuredWidth();
int height = view.getMeasureHeight();
}
});
}
三、ViewTreeObserver
使用ViewTreeObserver的眾多回調(diào)可以完成這個功能,比如使用OnGlobalLayoutListener接口,當(dāng)View樹的狀態(tài)發(fā)生改變或者View樹內(nèi)部的View的可見性發(fā)生改變時,onGlobalLayout方法將被回調(diào)。需要注意的是,伴隨著View樹的狀態(tài)改變等,onGlobalLayout方法會被回調(diào)多次。
protected void onStart() {
super.onStart();
ViewTreeObserver observer = view.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@SuppressWarnings("deprecation")
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
}
});
}
四、view.measure(int widthMeasureSpec, int heightMeasureSpec)
通過手動對View進行measure來得到View的寬/高。這種情況比較復(fù)雜,需要分情況處理,根據(jù)View的LayoutParams來分:
1.match_parent
無法measure出具體的寬/高。原因很簡單,根據(jù)View的measure過程,構(gòu)造此種MeasureSpec需要知道parentSize,即父容器的剩余空間,而這個時候我們無法知道parentSize,所以理論上不可能測量出View的大小。
2.固定大小
比如寬/高都是100px,代碼如下:
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY);
view.measure(widthMeasureSpec, heightMeasureSpec);
3.wrap_content
代碼如下:
int widthMeasureSpec = MeasureSpec.makeMeasureSpec((1 << 30) - 1, MeasureSpec.AT_MOST);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec((1 << 30) - 1, MeasureSpec.AT_MOST);
view.measure(widthMeasureSpec, heightMeasureSpec);
在最大化模式下,用View理論上能支持的最大值去構(gòu)造MeasureSpec是合理的。
例子:
//布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_layout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="100px">
<TextView
android:id="@+id/main_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, Android!"/>
<Button
android:id="@+id/main_btn"
android:layout_width="200px"
android:layout_height="wrap_content"
android:layout_marginTop="100px"
android:gravity="center"
android:textAllCaps="false"
android:text="Click"/>
</LinearLayout>
//代碼
private void testMeasureSpec() {
int widthMeasureSpec,heightMeasureSpec;
Logger.d("main_btn原始測量尺寸, width: " + mMainBtn.getMeasuredWidth() + ", height: " + mMainBtn.getMeasuredHeight());
//寬度設(shè)置SpecMode為EXACTLY,SpecSize為400
widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(400, View.MeasureSpec.EXACTLY);
heightMeasureSpec = View.MeasureSpec.makeMeasureSpec((1 << 30) - 1, View.MeasureSpec.AT_MOST);
mMainBtn.measure(widthMeasureSpec, heightMeasureSpec);
Logger.d("寬度設(shè)置SpecMode為 EXACTLY,SpecSize為 400");
Logger.d("main_btn測量尺寸, width: " + mMainBtn.getMeasuredWidth() + ", height: " + mMainBtn.getMeasuredHeight());
Logger.d("main_btn實際尺寸, width: " + mMainBtn.getWidth() + ", height: " + mMainBtn.getHeight());
//寬度設(shè)置SpecMode為AT_MOST,SpecSize為(1 << 30) - 1
widthMeasureSpec = View.MeasureSpec.makeMeasureSpec((1 << 30) - 1, View.MeasureSpec.AT_MOST);
heightMeasureSpec = View.MeasureSpec.makeMeasureSpec((1 << 30) - 1, View.MeasureSpec.AT_MOST);
mMainBtn.measure(widthMeasureSpec, heightMeasureSpec);
Logger.d("寬度設(shè)置SpecMode為 AT_MOST,SpecSize為 (1 << 30) - 1");
Logger.d("main_btn測量尺寸, width: " + mMainBtn.getMeasuredWidth() + ", height: " + mMainBtn.getMeasuredHeight());
Logger.d("main_btn實際尺寸, width: " + mMainBtn.getWidth() + ", height: " + mMainBtn.getHeight());
//寬度設(shè)置SpecMode為UNSPECIFIED,SpecSize為0
widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
heightMeasureSpec = View.MeasureSpec.makeMeasureSpec((1 << 30) - 1, View.MeasureSpec.AT_MOST);
mMainBtn.measure(widthMeasureSpec, heightMeasureSpec);
Logger.d("寬度設(shè)置SpecMode為 UNSPECIFIED,SpecSize為 0");
Logger.d("main_btn測量尺寸, width: " + mMainBtn.getMeasuredWidth() + ", height: " + mMainBtn.getMeasuredHeight());
Logger.d("main_btn實際尺寸, width: " + mMainBtn.getWidth() + ", height: " + mMainBtn.getHeight());
}
//log
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╔════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ Thread: main
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.onWindowFocusChanged (MainActivity.java:93)
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.testMeasureSpec (MainActivity.java:62)
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ main_btn原始測量尺寸, width: 200, height: 96
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╚════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╔════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ Thread: main
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.onWindowFocusChanged (MainActivity.java:93)
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.testMeasureSpec (MainActivity.java:67)
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ 寬度設(shè)置SpecMode為 EXACTLY,SpecSize為 400
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╚════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╔════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ Thread: main
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.onWindowFocusChanged (MainActivity.java:93)
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.testMeasureSpec (MainActivity.java:68)
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ main_btn測量尺寸, width: 400, height: 96
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╚════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╔════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ Thread: main
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.onWindowFocusChanged (MainActivity.java:93)
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.testMeasureSpec (MainActivity.java:69)
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ main_btn實際尺寸, width: 200, height: 96
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╚════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╔════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ Thread: main
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.onWindowFocusChanged (MainActivity.java:93)
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.testMeasureSpec (MainActivity.java:75)
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ 寬度設(shè)置SpecMode為 AT_MOST,SpecSize為 (1 << 30) - 1
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╚════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.243 15885-15885/com.tomorrow.androidtest2 D/zwm: ╔════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ Thread: main
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.onWindowFocusChanged (MainActivity.java:93)
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.testMeasureSpec (MainActivity.java:76)
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ main_btn測量尺寸, width: 176, height: 96
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╚════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╔════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ Thread: main
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.onWindowFocusChanged (MainActivity.java:93)
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.testMeasureSpec (MainActivity.java:77)
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ main_btn實際尺寸, width: 200, height: 96
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╚════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╔════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ Thread: main
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.onWindowFocusChanged (MainActivity.java:93)
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.testMeasureSpec (MainActivity.java:83)
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ 寬度設(shè)置SpecMode為 UNSPECIFIED,SpecSize為 0
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╚════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╔════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ Thread: main
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.onWindowFocusChanged (MainActivity.java:93)
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.testMeasureSpec (MainActivity.java:84)
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ main_btn測量尺寸, width: 176, height: 96
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╚════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╔════════════════════════════════════════════════════════════════════════════════════════
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ Thread: main
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.onWindowFocusChanged (MainActivity.java:93)
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ MainActivity.testMeasureSpec (MainActivity.java:85)
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╟────────────────────────────────────────────────────────────────────────────────────────
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ║ main_btn實際尺寸, width: 200, height: 96
03-25 12:58:55.253 15885-15885/com.tomorrow.androidtest2 D/zwm: ╚════════════════════════════════════════════════════════════════════════════════════════