Android獲取狀態欄高度、標題欄高度、編輯區域高度

1、Activity界面的劃分html

   

 簡單說明一下(上圖Activity採用默認Style,狀態欄和標題欄都會顯示):最大的草綠色區域是屏幕界面,紅色次大區域咱們稱之爲「應用程序界面區域」,最小紫色的區域咱們稱之爲「View繪製區域」;屏幕頂端、應用界面區以外的那部分顯示手機電池網絡運營商信息的爲「狀態欄」,應用區域頂端、View繪製區外部顯示Activity名稱的部分咱們稱爲「標題欄」。android

2、狀態高度的測量

        狀態欄是顯示顯示手機狀態(如電池電量、網絡狀態、時間、運營商信息等)的區域,通常內容型應用都會顯示保留狀態欄,可是遊戲界面若是還保留狀態欄就不合適了,由於遊戲界面要響應各類手勢,而狀態欄也會響應一些手勢,有可能引起錯誤操做,因此通常在遊戲界面都會隱藏狀態欄,使遊戲界面全屏顯示,關於設置全屏請查看 《Android設置Activity全屏的兩種方式及Theme屬性解析》,繼續看狀態欄高度測量:
        狀態欄高度的測量我在這裏提供4種方法:

      (1)經過系統尺寸資源獲取

        狀態欄高度定義在Android系統尺寸資源中status_bar_height,但這並非公開可直接使用的,例如像一般使用系統資源那樣android.R.dimen.status_bar_height。可是系統給咱們提供了一個Resource類,經過這個類能夠獲取資源文件,藉此能夠獲取到status_bar_height
/** 
* 獲取狀態欄高度——方法1 
* */  
int statusBarHeight1 = -1;  
//獲取status_bar_height資源的ID  
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");  
if (resourceId > 0) {  
    //根據資源ID獲取響應的尺寸值  
    statusBarHeight1 = getResources().getDimensionPixelSize(resourceId);  
}  
Log.e("-------", "狀態欄-方法1:" + statusBarHeight1)
(2)經過R類的反射
        你們都知道Android的全部資源都會有唯一標識在R類中做爲引用。咱們也能夠經過反射獲取R類的實例域,而後找status_bar_height
/** 
 * 獲取狀態欄高度——方法2 
 * */  
 int statusBarHeight2 = -1;  
 try {  
    Class<?> clazz = Class.forName("com.android.internal.R$dimen");  
    Object object = clazz.newInstance();  
    int height = Integer.parseInt(clazz.getField("status_bar_height")  
              .get(object).toString());  
    statusBarHeight2 = getResources().getDimensionPixelSize(height);  
 } catch (Exception e) {  
    e.printStackTrace();  
 }  
 Log.e("-------", "狀態欄-方法2:" + statusBarHeight2);  

(3)藉助應用區域的top屬性

        這就用到了開題時的那張屏幕區域劃分圖片,狀態欄位於屏幕最頂端,其位置從(0,0)開始,故而應用區域的頂端位置(高度 = Y座標 - 0)即爲狀態欄的高度
/** 
* 獲取狀態欄高度——方法3 
* 應用區的頂端位置即狀態欄的高度 
* *注意*該方法不能在初始化的時候用 
* */  
Rect rectangle= new Rect();  
getWindow().getDecorView().getWindowVisibleDisplayFrame(rectangle);  
//高度爲rectangle.top-0仍爲rectangle.top  
Log.e("-------", "狀態欄-方法3:" + rectangle.top); 
*注意*  若是單單獲取statusBar高度而不獲取titleBar高度時,這種方法並不推薦你們使用,由於這種方法依賴於WMS(窗口管理服務的回調)。正是由於窗口回調機制,因此在Activity初始化時執行此方法獲得的高度是0,這就是不少人獲取到statusBar高度爲0的緣由。這個方法推薦在回調方法onWindowFocusChanged()中執行,才能獲得預期結果

       (4)藉助屏幕和應用區域高度

        仍是看屏幕區域劃分圖,是否是狀態欄佔滿了屏幕中除應用區域以外的所有呢?因此直接上代碼
/** 
* 獲取狀態欄高度——方法4 
* 狀態欄高度 = 屏幕高度 - 應用區高度 
* *注意*該方法不能在初始化的時候用 
* */  
//屏幕  
DisplayMetrics dm = new DisplayMetrics();  
getWindowManager().getDefaultDisplay().getMetrics(dm);  
//應用區域  
Rect outRect1 = new Rect();  
getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect1);  
int statusBar = dm.heightPixels - outRect1.height();  //狀態欄高度=屏幕高度-應用區域高度  
Log.e("------------", "狀態欄-方法4:" + statusBar);  

       三、4這兩種方法其實本質是同樣,因此若是單單獲取statusBar高度而不獲取titleBar高度時也不推薦你們使用,理由同上方法3網絡

 3、標題欄高度的測量

        搞懂了上邊的原理,標題欄高度的測量也就手到擒來啦,依舊是屏幕區域劃分圖。這裏也給出兩種方法,先給出公共代碼吧,就是獲取各區域(*注意*依舊是在Activity的回調方法onWindowFocusChanged()中執行,才能獲得預期結果)
     //屏幕  
        DisplayMetrics dm = new DisplayMetrics();  
        getWindowManager().getDefaultDisplay().getMetrics(dm);  
        Log.e("-------", "屏幕高:" + dm.heightPixels);  
  
        //應用區域  
        Rect outRect1 = new Rect();  
        getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect1);  
        Log.e("------", "應用區頂部" + outRect1.top);  
        Log.e("-------", "應用區高" + outRect1.height());  
          
        //View繪製區域  
        Rect outRect2 = new Rect();  
        getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(outRect2);   
        Log.e("--------", "View繪製區域頂部-錯誤方法:" + outRect2.top);   //不能像上邊同樣由outRect2.top獲取,這種方式得到的top是0,多是bug吧  
        int viewTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();   //要用這種方法  
        Log.e("--------", "View繪製區域頂部-正確方法:" + viewTop);  
        Log.e("--------", "View繪製區域高度:" + outRect2.height());  

有時候獲取View繪製區時列出來的那個outRect2.top=0app

(1)top-top

/** 
* 獲取標題欄高度-方法1 
* 標題欄高度 = View繪製區頂端位置 - 應用區頂端位置(也能夠是狀態欄高度,獲取狀態欄高度方法3中說過了) 
* */  
int titleHeight1 = viewTop - outRect1.top;  
Log.e("--------", "標題欄高度-方法1:" + titleHeight1);

(2)高度-高度

/** 
* 獲取標題欄高度-方法2 
* 標題欄高度 = 應用區高度 - View繪製區高度 
 * */  
int titleHeight2 = outRect1.height() - outRect2.height();  
Log.e("----------", "標題欄高度-方法2:" + titleHeight2); 

       4、注意事項

        *注意* spa

        (1)無論你是否設置全屏模式,或是不顯示標題欄,在使用獲取狀態欄高度方法1和獲取狀態欄高度方法2都會測量到狀態欄的高度,理解原理就不難解釋——系統資源屬性是固定的、真實的,無論你是否隱瞞(隱藏或者顯示),它都在那裏;code

        (2)可是若使用獲取狀態欄高度方法3和獲取狀態欄高度方法4,以及獲取標題欄高度方法1和獲取標題欄高度方法2,都是依賴於WMS,是在界面構建後根據View獲取的,因此顯示了就有高度,不顯示天然沒高度了。htm

    下面是驗證blog

    先設置Activity爲全屏遊戲

 

<activity  
android:name=".MainActivity"  
android:label="@string/app_name"  
            android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen"  
android:screenOrientation="portrait" >  
<intent-filter>  
      <action android:name="android.intent.action.MAIN" />  
  
      <category android:name="android.intent.category.LAUNCHER" />  
       </intent-filter>  
</activity>  

        屏幕各區域獲取不變;圖片

 

        輸出StatusBar和titleBar高度信息

int titleHeight1 = viewTop - outRect1.top;  
Log.e("--------", "驗證Statue高度:" + titleHeight1);  
Log.e("--------", "驗證Title高度:" + outRect1.top);