編輯:關於Android編程
上一個github小項目中我們介紹了防止按鈕重復點擊的小框架,其實現的核心邏輯是重寫OnClickListener的onClick方法,添加防止重復點擊的邏輯,即為第二次點擊與第一次點擊的時間間隔添加阙值,若第二次點擊的時間間隔與第一次點擊的時間間隔小於阙值,則此次點擊無效,再次基礎上我們又封裝了點擊組件驗證網絡Listener,點擊組件驗證是否登錄Listener等
本文中我將介紹一下android中Activity啟動時獲取組件寬高的三種方式。我們知道,有時候我們需要在Activity啟動的時候獲取某一組件的寬或者是高用於動態的更改UI布局文件,但是這時候我們直接通過getWidth和getHeight方法獲取是有問題的。為什麼這麼說呢?這裡我們可以下一個測試的例子來驗證一下:
問題:
/**
* 在onCreate方法中調用,用於獲取TextView的寬度和高度
*/
private void getTextHeightAndWidth() {
// 我們定義的用於獲取寬度和高度的組件
titleText = (TextView) findViewById(R.id.text_title);
int height = titleText.getHeight();
int width = titleText.getWidth();
Log.i(TAG, "height:" + height + " " + "width:" + width);
}
這段代碼看似是正常沒有問題的,但是我們將調用的代碼寫在onCreate方法的時候,執行這段代碼之後,打印的結果:
06-26 20:12:15.356 19453-19453/uuch.com.android_viewheight I/MainActivity: height:0 width:0
咦?為什麼打印的height和width都是0呢?我們在執行一遍呢?結果還是一樣的,兩個變量都是0,難道這段代碼不能再onCreate方法中調用,那麼我們試試在onResume方法中調用呢?
只能說然並卵,打印的結果依然是:
06-26 20:52:13.986 19453-19453/uuch.com.android_viewheight I/MainActivity: height:0 width:0
好吧,問題已經出來了,看樣子我們是不能再onCreate方法或者是onResume方法中調用該方法獲取組件的寬高的,但是這是為什麼呢?平時我們都是通過這個方法來獲取組件的寬高的,並且也沒問題啊,比如我們將這個方法的調用邏輯寫在按鈕的點擊事件之內呢?我們再來試試。
/**
* 這裡的button1是我們定義的Button組件,並且我們重寫了Button的點擊事件,在其中調用了獲取組件寬高的方法
*/
button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getTextHeightAndWidth();
}
});
這樣敲完代碼之後,我們執行這段代碼,界面入下圖所示:
那麼我們的打印結果呢?
06-26 20:57:08.188 22648-22648/uuch.com.android_viewheight I/MainActivity: height:57 width:225
恩?這時候我們發現其打印出了組件的寬和高,那麼為什麼我們在Activity的onCreate、onResume方法中打印的時候,輸出的組件寬高都是為0呢?
原因:
Activity的啟動流程和Activity的布局文件加載繪制流程,其實沒有相關的關系的,其實兩個異步的加載流程,這樣我們在Activity的onCreate和onResume方法調用textView.getHeight或者是textView.getWidth方法的時候,其組件並沒有執行完繪制流程,因此此時獲取到的組件的寬高都是默認的0,也就是無法獲取組件的寬和高。
但是當我們將獲取組件寬高的方法卸載按鈕的點擊事件的時候,由於此時按鈕已經顯示出來了,所以證明布局文件已經加載繪制完成,這時候點擊組件執行組件的獲取寬高方法,就能正常的獲取到組件的寬和高了。
這也就是為什麼我們在onCreate和onResume方法中調用獲取組件寬高都是0,而在按鈕的點擊事件中獲取的時候正常的原因了。
其他解決方案:
那麼如果我們想在Activity的onCreate方法或者是onReusme方法獲取組件的寬高怎麼辦呢?這裡提供了以下的三種方式:
重寫Activity的onWindowFocusChanged方法
/**
* 重寫Acitivty的onWindowFocusChanged方法
*/
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
/**
* 當hasFocus為true的時候,說明Activity的Window對象已經獲取焦點,進而Activity界面已經加載繪制完成
*/
if (hasFocus) {
int widht = titleText.getWidth();
int height = titleText.getHeight();
Log.i(TAG, "onWindowFocusChanged width:" + widht + " "
+ " height:" + height;
}
}
說明:
這樣重寫onWindowFocusChanged方法,當獲取焦點的時候我們就可以通過getWidth和getHeight方法得到組件的寬和高了。但是這時候這個方法的邏輯可能會執行多次,也就是說只要我們的Activity的window對象獲取了焦點就會執行該語句,所以我們需要做一些邏輯判斷,讓它在我們需要打印獲取組件寬高的時候在執行。
為組件添加OnGlobalLayoutListener事件監聽
/**
* 為Activity的布局文件添加OnGlobalLayoutListener事件監聽,當回調到onGlobalLayout方法的時候我們通過getMeasureHeight和getMeasuredWidth方法可以獲取到組件的寬和高
*/
private void initOnLayoutListener() {
final ViewTreeObserver viewTreeObserver = this.getWindow().getDecorView().getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Log.i(TAG, "開始執行onGlobalLayout().........");
int height = titleText.getMeasuredHeight();
int width = titleText.getMeasuredWidth();
Log.i(TAG, "height:" + height + " width:" + width);
}
});
}
說明:
需要說明的是這裡的onGlobalLayout方法會在Activity的組件執行完onLayout方法之後執行,這裡的onLayout方法主要用於計算組件的寬高操作,具體可參考:android源碼解析(十八)–>Activity布局繪制流程,這樣當我們計算完組件的寬高之後再執行獲取組件的寬高操作,自然能夠獲取到組件的寬度和高度。
為組件添加OnPreDrawListener事件監聽
/**
* 初始化viewTreeObserver事件監聽,重寫OnPreDrawListener獲取組件高度
*/
private void initOnPreDrawListener() {
final ViewTreeObserver viewTreeObserver = this.getWindow().getDecorView().getViewTreeObserver();
viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
Log.i(TAG, "開始執行onPreDraw().........");
int height = titleText.getMeasuredHeight();
int width = titleText.getMeasuredWidth();
Log.i(TAG, "height:" + height + " width:" + width);
return true;
}
});
}
說明:
需要說明的是這裡的onPreDraw方法會在Activity的組件執行onDraw方法之前執行,熟悉我們Activity組件加載繪制流程的同學應該知道,這裡的onDraw方法主要用於執行真正的繪制組件操作,而這時候我們已經計算出來了組件的位置,寬高等操作,這樣之後再執行獲取組件的寬高操作,自然能夠獲取到組件的寬度和高度。
其他說明:
需要說明的是如果對Acitivty的布局加載繪制流程比較了解的同學應該知道,界面的顯示過程經過了:測量位置,測量大小,繪制,三個操作流程。而我們獲取組件的寬高就是獲取組件的大小,所以我們獲取的代碼必須要在組件執行完測量大小之後,而無論是我們添加的onWindowFocusChanged方法,onPreDrawListener監聽,已經onGlobalLayoutListener監聽其實都是在組件完成了測量大小之後執行了,因此這時候我們能夠正確的獲取到組件的寬和高。
總結:
該類庫主要是介紹了三種我們在Activity的啟動過程中獲取組件寬高的方式;
通過重寫onWidnowFocusChanged方法獲取組件寬高的方式,可能會回調幾次,這點需要我們注意;
項目保存地址:android-viewheight,歡迎star和follow
Android N 仍處於活動的開發狀態,但現在您可以將其作為 N Developer Preview 的一部分進行試用。 以下部分重點介紹面向開發者的一些新功能。請務必
作者:Mark Liu 下載樣本代碼 簡介 隨機旋轉 該選擇可支持渲染視頻的平面隨著橫、縱軸呈 3D 效果隨機旋轉。此外,它還可定期在屏幕上呈現
當我們在手機上安裝360安全衛士時,手機屏幕上時刻都會出現一個小浮動窗口,點擊該浮動窗口可跳轉到安全衛士的操作界面,而且該浮動窗口不受其他activity的覆蓋影響仍然可
簡介MPAndroidChart是PhilJay大神給Android開發者帶來的福利。MPAndroidChart是一個功能強大並且使用靈活的圖表開源庫,支持Androi