獲取Android手機(jī)屏幕各個(gè)區(qū)域的寬高尺寸

屏幕物理寬高

一般來說計(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下字柠,稍微修改一下代碼也就可以獲得了探越。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市窑业,隨后出現(xiàn)的幾起案子阀坏,更是在濱河造成了極大的恐慌另凌,老刑警劉巖必指,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恨搓,死亡現(xiàn)場(chǎng)離奇詭異酒唉,居然都是意外死亡蜕径,警方通過查閱死者的電腦和手機(jī)于毙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門趾盐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來哥倔,“玉大人秸架,你說我怎么就攤上這事∨剌铮” “怎么了东抹?”我有些...
    開封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)沃测。 經(jīng)常有香客問我缭黔,道長(zhǎng),這世上最難降的妖魔是什么蒂破? 我笑而不...
    開封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任馏谨,我火速辦了婚禮,結(jié)果婚禮上附迷,老公的妹妹穿的比我還像新娘惧互。我一直安慰自己哎媚,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開白布喊儡。 她就那樣靜靜地躺著拨与,像睡著了一般。 火紅的嫁衣襯著肌膚如雪艾猜。 梳的紋絲不亂的頭發(fā)上买喧,一...
    開封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音匆赃,去河邊找鬼淤毛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛算柳,可吹牛的內(nèi)容都是我干的钱床。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼埠居,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼查牌!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起滥壕,我...
    開封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤纸颜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后绎橘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胁孙,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年称鳞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了涮较。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡冈止,死狀恐怖狂票,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情熙暴,我是刑警寧澤闺属,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站周霉,受9級(jí)特大地震影響掂器,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜俱箱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一国瓮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦乃摹、人聲如沸厂财。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽璃饱。三九已至,卻和暖如春肪康,著一層夾襖步出監(jiān)牢的瞬間荚恶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工磷支, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留谒撼,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓雾狈,卻偏偏與公主長(zhǎng)得像廓潜,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子善榛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容