屏幕物理寬高
一般來說計(jì)算屏幕寬高都會(huì)使用以下方法:
public static int getScreenWidth(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
return dm.widthPixels;
}
public static int getScreenHeight(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
return dm.heightPixels;
}
但在有虛擬按鍵(NavigationBar)的屏幕上唤蔗,不管是橫屏還是豎屏,NavigationBar占了位置的那一邊得到的結(jié)果就會(huì)不準(zhǔn)確柳沙。獲得的結(jié)果其實(shí)是真實(shí)長(zhǎng)度 - NavigationBar的高度
于是為了在有NavigationBar的屏幕上也能準(zhǔn)確的計(jì)算到屏幕的寬高岩灭,就有了以下方法:
public static int getRealWidth(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
int screenWidth = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
DisplayMetrics dm = new DisplayMetrics();
display.getRealMetrics(dm);
screenWidth = dm.widthPixels;
//或者也可以使用getRealSize方法
// Point size = new Point();
// display.getRealSize(size);
// screenWidth = size.x;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
try {
screenWidth = (Integer) Display.class.getMethod("getRawWidth").invoke(display);
} catch (Exception e) {
DisplayMetrics dm = new DisplayMetrics();
display.getMetrics(dm);
screenWidth = dm.widthPixels;
}
}
return screenWidth;
}
public static int getRealHeight(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
int screenHeight = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
DisplayMetrics dm = new DisplayMetrics();
display.getRealMetrics(dm);
screenHeight = dm.heightPixels;
//或者也可以使用getRealSize方法
// Point size = new Point();
// display.getRealSize(size);
// screenHeight = size.y;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
try {
screenHeight = (Integer) Display.class.getMethod("getRawHeight").invoke(display);
} catch (Exception e) {
DisplayMetrics dm = new DisplayMetrics();
display.getMetrics(dm);
screenHeight = dm.heightPixels;
}
}
return screenHeight;
}```
#狀態(tài)欄的高度
狀態(tài)欄(StatusBar)是屏幕頂部顯示手機(jī)狀態(tài)(如電池電量、網(wǎng)絡(luò)狀態(tài)赂鲤、時(shí)間噪径、運(yùn)營(yíng)商信息等)的區(qū)域。其高度可以通過讀取定義在Android系統(tǒng)尺寸資源中的status_bar_height獲得数初,所以不管當(dāng)前Activity有沒有隱藏StatusBar找爱,獲得的結(jié)果都是一樣的。
```java
public static int getStatusBarHeight(Context context) {
int statusBarHeight = -1;
Resources resources = context.getResources();
int resourceId = resources.getIdentifier("status_bar_height", "dimen","android");
if (resourceId > 0) {
statusBarHeight = resources.getDimensionPixelSize(resourceId);
}
return statusBarHeight;
}
虛擬按鍵的高度
虛擬按鍵(NavigationBar)是部分Android手機(jī)屏幕底部用以取代物理按鍵的區(qū)域泡孩,可隱藏车摄。其高度可以通過讀取定義在Android系統(tǒng)尺寸資源中的navigation_bar_height獲得,所以不管當(dāng)前Activity有沒有隱藏NavigationBar仑鸥,獲得的結(jié)果都是一樣的吮播。
public static int getNavigationBarHeight(Context context) {
int navigationBarHeight = -1;
Resources resources = context.getResources();
int resourceId = resources.getIdentifier("navigation_bar_height","dimen", "android");
if (resourceId > 0) {
navigationBarHeight = resources.getDimensionPixelSize(resourceId);
}
return navigationBarHeight;
}
ActionBar的高度
ActionBar就是在帶有ActionBar的Theme中StatusBar下方、Activity頂部的類似于標(biāo)題欄的區(qū)域眼俊。其高度可以通過讀取定義在Android系統(tǒng)屬性資源中的actionBarSize獲得意狠,所以不管當(dāng)前Activity有沒有使用ActionBar,獲得的結(jié)果都是一樣的疮胖。
public static float getActoinBarHeight(Context context) {
TypedArray actionbarSizeTypedArray = context.obtainStyledAttributes(new int[] {
android.R.attr.actionBarSize
});
return actionbarSizeTypedArray.getDimension(0, 0);
}
ContentView的高度
一般來說环戈,ContentView就是我們?yōu)锳ctivity設(shè)計(jì)的layout布局然后通過setContentView添加到Window上的那個(gè)View了。該方法推薦在onWindowFocusChanged()中執(zhí)行澎灸,在onCreate()等方法中執(zhí)行會(huì)返回0院塞。
public static int getContentViewHeight(Activity activity) {
Rect rectangle= new Rect();
activity.getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(rectangle);
return rectangle.height();
}
WindowVisibleDisplay的高度
這個(gè)不太好解釋,一般來說就是我們的程序能顯示(或者說可見)的區(qū)域击孩。返回結(jié)果受StatusBar迫悠、NavigationBar和軟鍵盤等顯示/消失的狀態(tài)影響。當(dāng)Activity隱藏了StatusBar巩梢、NavigationBar和軟鍵盤處于全屏狀態(tài)時(shí)创泄,這個(gè)區(qū)域的大小就是屏幕的大小艺玲,即使Activity的Theme是Theme.Dialog之類。該方法推薦在onWindowFocusChanged()中執(zhí)行鞠抑,在onCreate()等方法中執(zhí)行會(huì)返回0饭聚。
public static int getWindowVisibleDisplayHeight(Activity activity) {
Rect rectangle= new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rectangle);
return rectangle.height();
}
軟鍵盤的高度
上面說了軟鍵盤的顯示/消失可能會(huì)影響WindowVisibleDisplay的高度,可以據(jù)此來獲得軟鍵盤的高度搁拙。
//ViewTree的狀態(tài)發(fā)生改變或者ViewTree內(nèi)部的View的可見性發(fā)生改變時(shí)均會(huì)調(diào)用onGlobalLayout方法秒梳,不用時(shí)記得移除掉監(jiān)聽
getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener(){
@Override
public void onGlobalLayout(){
//rootViewHeight可以理解為屏幕的高度
int rootViewHeight = getWindow().getDecorView().getRootView().getHeight();
//程序可視區(qū)域的高度
int windowVisibleDisplayHeight = ScreenSizeUtils.getWindowVisibleDisplayHeight(ScreenActivity.this);
//判斷軟鍵盤是否顯示的一個(gè)閥值
boolean keyboardShow = (rootViewHeight - windowVisibleDisplayHeight) > rootViewHeight / 3;
if (keyboardShow) {
int keyboardHeight = rootViewHeight - windowVisibleDisplayHeight;
Log.i("tag", "keyboardHeight: " + keyboardHeight);
}
}
});
- 因?yàn)槭潜O(jiān)聽回調(diào),上面的方法在Activity的onCreate方法中也有效
- 當(dāng)Activity的windowSoftInputMode 屬性為"adjustNothing"模式時(shí)以上方法無效
- 監(jiān)聽不僅在軟鍵盤顯示/消失時(shí)會(huì)被調(diào)用箕速,ViewTree的狀態(tài)發(fā)生改變或者ViewTree內(nèi)部的View的可見性發(fā)生改變時(shí)均會(huì)調(diào)用酪碘,所以不用時(shí)記得移除掉監(jiān)聽,可以在onDestroy方法里面進(jìn)行移除:
@Override
protected void onDestroy() {
//移除布局變化監(jiān)聽
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
getWindow().getDecorView().getViewTreeObserver().removeOnGlobalLayoutListener(mLayoutChangeListener);
} else {
getWindow().getDecorView().getViewTreeObserver().removeGlobalOnLayoutListener(mLayoutChangeListener);
}
super.onDestroy();
}
- 上面的方法稍微修改一下就可以添加對(duì)軟鍵盤顯示/消失的監(jiān)聽
以上搜集的大部分都是獲取各個(gè)區(qū)域的高度盐茎,其寬度我們一般都不關(guān)心兴垦,因?yàn)橐话愣际瞧聊坏膶挾龋绻皇堑那闆r下字柠,稍微修改一下代碼也就可以獲得了探越。