標籤:android blog http java 使用 os
擷取螢幕寬高尺寸的三種代碼形式
在Android上,目前我知道的擷取螢幕尺寸的方法有三種不同的代碼形式
方法1.在Activity中最常見的調用方式
WindowManager windowManager = getWindowManager();
Display display = windowManager.getDefaultDisplay();
int screenWidth = display.getWidth();
int screenHeight = display.getHeight();
由於在API Level 13以後上述的getWidth和getHeight包括getOrientation都變成了@Deprecated,所以螢幕寬高用getSize替換,也就有了方法2
Point outSize = new Point();
display.getSize(outSize);
screenWidth = outSize.x;
screenHeight = outSize.y;
顯然要做API Level的區分感覺會不太舒服,那麼就有了第三種通用形式
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
screenWidth =dm.widthPixels;
screenHeight =dm.heightPixels;
其實上述三種代碼形式,調用的都是WindowManager的default Display object裡面的寬高尺寸,有些地方說上述這三種形式在螢幕未顯示時是拿不到具體值的,會拿到全是0的情況,我在Activity的onCreate函數中進行對其調用發現是能取到具體數值的,而且即使不在Activity中,通過Application的onCreate函數中的如下代碼:
((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(dm);
也能順利拿到具體的螢幕寬高值。
擷取狀態列的尺寸
由於decorView是window中的最頂層view,可以從window中擷取到decorView,然後decorView有個getWindowVisibleDisplayFrame方法可以擷取到程式顯示的地區,包括標題列,但不包括狀態列。
於是就有了算出狀態列高度的第一種代碼形式
Rect frame = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
上述代碼有時候擷取到的高度是0,網上說法是在4.0.3版本以後的都會返回0,我沒有親測,但是在我的真機上確實拿到是0,網上流出一種在源碼程式中擷取狀態列高度的代碼:
statusBarHeight = getResources().getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
那麼在非源碼中應該怎麼擷取呢?網上流行的一種解決方案,就是對上述需要源碼的實現方式通過反射來實現狀態列高度的擷取,具體代碼如下:
import java.lang.reflect.Field;
//擷取手機狀態列高度
public static int getStatusBarHeight(Context context){
Class<?> c = null;
Object obj = null;
Field field = null;
int x = 0, statusBarHeight = 38;//通常這個值會是38
try {
c = Class.forName("com.android.internal.R$dimen");
obj = c.newInstance();
field = c.getField("status_bar_height");
x = Integer.parseInt(field.get(obj).toString());
statusBarHeight = context.getResources().getDimensionPixelSize(x);
} catch (Exception e1) {
e1.printStackTrace();
}
return statusBarHeight;
}
經過測試發現這個函數在狀態列隱藏的時候獲得的值和狀態列顯示時的值是一樣的,不會變化,而且在做橫豎屏測試時,也是一樣不會改變,即狀態列的高度在手機上應該是固定的。
上面方法是參考了網上有個擷取狀態列高度的文章而來的
http://www.cnblogs.com/renkangke/archive/2013/05/27/3101375.html
擷取標題列高度
上面講了擷取狀態列,順帶就引出如何擷取標題列高度的問題,目前我所知道的擷取標題列高度的方法是不能在onCreate函數中直接使用,必須在UI顯示出來後調用,具體大概是layout之後進行調用吧,具體代碼如下:
int contentTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
//statusBarHeight是上面所求的狀態列的高度
int titleBarHeight = contentTop – statusBarHeight;
上述方法的原理就是getWindow().findViewById(Window.ID_ANDROID_CONTENT)這個方法擷取到的view是程式不包括標題列的部分。由於不能直接在onCreate函數中調用,所以有些調用方法是在onCreate中起一個線程,然後延時調用。
我也不知道有什麼方法可以更加靠譜的擷取標題列高度,如果有哪位技術牛人知道還望告知,另外這種方法與ContentView中的其它控制項的尺寸擷取一樣,在onCreate中是無法直接擷取的,直接擷取都會是0。
另外在代碼中我們使用的是具體的像素值,具體像素值是與裝置相關的,我們一般不在代碼中直接使用具體使用像素值,而是在資源檔中定義好裝置無關的dp數值,然後通過類似如下方法擷取具體的像素值
int padding = getResources().getDimensionPixelSize(R.dimen.broadcast_select_padding);
有時候也有一種具體數值的方法來擷取像素值,比如上述的R.dimen.broadcast_select_padding假如是16dp,則可以通過下述方法擷取像素值
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int padding = 16 * dm.scaledDensity
但是這種方法我並不建議使用,因為Android的裝置品類太多,在有些手機上這種乘法獲得的值與getResources().getDimensionPixelSize獲得的值並不相等,而後者肯定比前者準確。