getWindowVisibleDisplayFrame()使用總結(jié)

im類(lèi)項(xiàng)目的聊天界面中需要在鍵盤(pán)上顯示一個(gè)輸入控制框缩举,所以需要獲取到軟鍵盤(pán)的高度先嬉,這里就需要使用到android中的getWindowVisibleDisplayFrame()方法墅冷。收集整理了一些getWindowVisibleDisplayFrame()的相關(guān)資料仇冯,這里記錄一下備忘进萄。

getWindowVisibleDisplayFrame()是View類(lèi)下的一個(gè)方法,用來(lái)獲取當(dāng)前窗口可視區(qū)域的大小磁玉。該方法原型為:

public void getWindowVisibleDisplayFrame(Rect outRect);

outRect中保存了可視區(qū)域的范圍,如left, top, right, bottom驾讲。

該方法使用注意事項(xiàng)
  1. 調(diào)用該方法的view對(duì)象必須在有效的window中蚊伞,比如activity,fragment或者dialog的layout中。類(lèi)似new TextView(context).getWindowVisibleDisplayFrame(rect)無(wú)法得到正確的結(jié)果吮铭。
  2. 該方法必須在view已經(jīng)attach到window時(shí)調(diào)用才能得到期望的正確結(jié)果时迫。比如我們可以在A(yíng)ctivity、Fragment和Dialog的onWindowFocusChanged()方法中執(zhí)行谓晌,在view的onAttachedToWindow()中可能無(wú)法獲得正確結(jié)果
  3. outRect所表示的只是窗體可見(jiàn)范圍掠拳,其會(huì)受到系統(tǒng)狀態(tài)欄,虛擬鍵盤(pán)和導(dǎo)航欄的影響纸肉,狀態(tài)欄主要影響outRect的top值溺欧,虛擬鍵盤(pán)和導(dǎo)航欄會(huì)影響outRect的bottom值
getWindowVisibleDisplayFrame()的應(yīng)用場(chǎng)景

由于A(yíng)ndroid系統(tǒng)并沒(méi)有提供api來(lái)獲取系統(tǒng)狀態(tài)欄喊熟,軟鍵盤(pán)和導(dǎo)航欄的高度,所以我們通常使用getWindowVisibleDisplayFrame()來(lái)得到這些模塊的值姐刁。對(duì)系統(tǒng)狀態(tài)欄高度芥牌,獲取一個(gè)非全屏,且窗口的LayoutParams的height設(shè)置為WindowManager.LayoutParams.MATCH_PARENT的窗口可視區(qū)域大小聂使,其top值就是狀態(tài)欄的高度壁拉。對(duì)系統(tǒng)軟鍵盤(pán),獲取一個(gè)高度是MATCH_PARENT的窗口在軟鍵盤(pán)顯示和隱藏兩種不同狀態(tài)下的可視區(qū)域大小柏靶,將bottom值相減就可以得到軟鍵盤(pán)的高度弃理。對(duì)系統(tǒng)虛擬按鍵欄,獲取一個(gè)高度是MATCH_PARENT的窗口在虛擬按鍵顯示和隱藏兩種不同狀態(tài)下的可視區(qū)域大小屎蜓,將bottom值相減就可以得到虛擬按鍵的高度案铺。

下面提供獲取狀態(tài)欄,虛擬鍵盤(pán)和導(dǎo)航欄的幾種方法:
public static int getStatusBarHeight(Context context) {
    int statusbarheight = 0;
    try {
            Class<?> c = Class.forName("com.android.internal.R$dimen");
            Object o = c.newInstance();
            Field field = c.getField("status_bar_height");
            int x = (Integer) field.get(o);
            statusbarheight = context.getResources().getDimensionPixelSize(x);
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    return statusbarheight;
}
    
public static int getStatusBarHeight(View view) {
    Rect outRect = new Rect();
    view.getWindowVisibleDisplayFrame(outRect);
    statusbarheight = outRect.top;  
    return outRect.top;
}

/**
* 獲取軟鍵盤(pán)高度
*/
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            Rect rect = new Rect();
            int windowVisibleBottomWithoutKeyboard;
            
            @Override
            public void onGlobalLayout() {
                rect.setEmpty();
                view.getWindowVisibleDisplayFrame(rect);
                int detal = windowVisibleBottomWithoutKeyboard - rect.bottom;
                if (detal > screenHeight / 3) {
                    keyboardHeight = detal;
                } else {
                    windowVisibleBottomWithoutKeyboard = rect.bottom;
                } 
            }
        });
        
public static int getNavBarHeight(Context context){
    if (isMeizu()) {
        return getSmartBarHeight(context);
    }
    if (checkDeviceHasNavigationBar(context)) {
        Resources resources = context.getResources();
        int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
        if (resourceId > 0) {
            return resources.getDimensionPixelSize(resourceId);
        }
    }
    return 0;
}

public static boolean checkDeviceHasNavigationBar(Context context) {
        boolean hasNavigationBar = false;
        Resources rs = context.getResources();
        int id = rs.getIdentifier("config_showNavigationBar", "bool", "android");
        if (id > 0) {
            hasNavigationBar = rs.getBoolean(id);
        }
        
        String navBarOverride = getSystemProperty("qemu.hw.mainkeys", "");
        if ("1".equals(navBarOverride)) {
            hasNavigationBar = false;
        } else if ("0".equals(navBarOverride)) {
            hasNavigationBar = true;
        }
        
        return hasNavigationBar;

}

public static boolean isMeizu() {
    /* 獲取魅族系統(tǒng)操作版本標(biāo)識(shí)*/
    String meizuFlymeOSFlag = getSystemProperty("ro.build.display.id", "");
    if (TextUtils.isEmpty(meizuFlymeOSFlag)) {
        return false;
    } else if (meizuFlymeOSFlag.contains("flyme") || meizuFlymeOSFlag.toLowerCase().contains("flyme")) {
        return true;
    } else {
        return false;
    }
}

public static int getSmartBarHeight(Context context) {
    try {
        Class c = Class.forName("com.android.internal.R$dimen");
        Object obj = c.newInstance();
        Field field = c.getField("mz_action_button_min_height");
        int height = Integer.parseInt(field.get(obj).toString());
        return context.getResources().getDimensionPixelSize(height);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return 0;

參考文檔

Android獲取窗口可視區(qū)域大小: getWindowVisibleDisplayFrame()

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末梆靖,一起剝皮案震驚了整個(gè)濱河市控汉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌返吻,老刑警劉巖姑子,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異测僵,居然都是意外死亡街佑,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)捍靠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)沐旨,“玉大人,你說(shuō)我怎么就攤上這事榨婆〈判” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵良风,是天一觀(guān)的道長(zhǎng)谊迄。 經(jīng)常有香客問(wèn)我,道長(zhǎng)烟央,這世上最難降的妖魔是什么统诺? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮疑俭,結(jié)果婚禮上粮呢,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好啄寡,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布豪硅。 她就那樣靜靜地躺著,像睡著了一般这难。 火紅的嫁衣襯著肌膚如雪舟误。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,071評(píng)論 1 285
  • 那天姻乓,我揣著相機(jī)與錄音嵌溢,去河邊找鬼。 笑死蹋岩,一個(gè)胖子當(dāng)著我的面吹牛赖草,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播剪个,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼秧骑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了扣囊?” 一聲冷哼從身側(cè)響起乎折,我...
    開(kāi)封第一講書(shū)人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎侵歇,沒(méi)想到半個(gè)月后骂澄,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惕虑,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年坟冲,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溃蔫。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡健提,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出伟叛,到底是詐尸還是另有隱情私痹,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布痪伦,位于F島的核電站侄榴,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏网沾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一蕊爵、第九天 我趴在偏房一處隱蔽的房頂上張望辉哥。 院中可真熱鬧,春花似錦、人聲如沸醋旦。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)饲齐。三九已至钉凌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間捂人,已是汗流浹背御雕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留滥搭,地道東北人酸纲。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像瑟匆,于是被迫代替她去往敵國(guó)和親闽坡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

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

  • 獲取窗口可視區(qū)域大小: getWindowVisibleDisplayFrame() 是View類(lèi)下的一個(gè)方法愁溜,從...
    Master_Yang閱讀 717評(píng)論 0 0
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,510評(píng)論 25 707
  • 問(wèn)答題47 /72 常見(jiàn)瀏覽器兼容性問(wèn)題與解決方案疾嗅? 參考答案 (1)瀏覽器兼容問(wèn)題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 13,728評(píng)論 1 92
  • 演講大舞臺(tái) 很多年以前,我在一家連鎖店工作冕象,一天老板請(qǐng)行業(yè)中的一位老師來(lái)給我們講課代承。當(dāng)時(shí)所有同事加起...
    17_陸小鳳琴閱讀 189評(píng)論 0 0
  • 六月次泽,一家歡喜一家憂(yōu)的日子也已經(jīng)過(guò)去,有人實(shí)習(xí)席爽,有人繼續(xù)學(xué)習(xí)意荤。選擇去哪里也不過(guò)一個(gè)短暫的決定而已,就像開(kāi)學(xué)的九月只锻,...
    失憶無(wú)效閱讀 381評(píng)論 2 3