全面屏虛擬鍵適配方案

寫之前先吐槽下自己碍沐,工作了這么多年辙浑,終于能靜下心來寫博客了

最近公司有個(gè)需求激涤,要實(shí)現(xiàn)類似于抖音的小視頻全屏播放的樣式,當(dāng)虛擬鍵盤展示的時(shí)候判呕,豎屏視頻就撐滿整個(gè)屏幕倦踢,當(dāng)虛擬鍵盤隱藏的時(shí)候,就需要讓視頻底部距離屏幕底部有個(gè)虛擬鍵高度的黑邊侠草,總結(jié)起來就是要保持視頻的原始比例辱挥,效果如下圖:

虛擬鍵顯示

虛擬鍵隱藏

所以,我們要做的很簡單边涕,就是監(jiān)聽NavigationBar的顯示和隱藏晤碘。

方案一:監(jiān)聽一個(gè)全屏 View的高度

之前看到一個(gè)思路是,使用addOnGlobalLayoutListener監(jiān)聽一個(gè)全屏 View 的高度功蜓,然后不停的去檢測(cè)當(dāng)前是否展示了 NavigationBar园爷,個(gè)人不太喜歡這個(gè)方案,有興趣可以自行查找式撼。

方案二:監(jiān)聽數(shù)據(jù)庫System表字段變化

該方案通過監(jiān)控settings數(shù)據(jù)庫System表中navigationbar_is_min的變化童社,來判斷當(dāng)前是否顯示虛擬鍵盤。經(jīng)過測(cè)試著隆,部分手機(jī)onChange方法并不會(huì)觸發(fā)扰楼。

經(jīng)過多番查證,問題有兩個(gè):

1.原來android5.0之后增加了多用戶的特性美浦,虛擬鍵盤的navigationbar_is_min字段從Settings.db的System表格移到了Global表弦赖。

2.不同手機(jī)品牌使用的注冊(cè)字段也不一樣。

優(yōu)化后的方法如下:

  private void initDeviceInfo() {
        String brand = Build.BRAND;
        if (brand.equalsIgnoreCase("HUAWEI")) {
            mDeviceInfo = "navigationbar_is_min";
        } else if (brand.equalsIgnoreCase("XIAOMI")) {
            mDeviceInfo = "force_fsg_nav_bar";
        } else if (brand.equalsIgnoreCase("VIVO")) {
            mDeviceInfo = "navigation_gesture_on";
        } else if (brand.equalsIgnoreCase("OPPO")) {
            mDeviceInfo = "navigation_gesture_on";
        } else {
            mDeviceInfo = "navigationbar_is_min";
        }
    }
     /**
     * 注冊(cè)監(jiān)聽實(shí)時(shí)監(jiān)控虛擬鍵
     */
    private void registerNavigationBarObserver() {
        if (null == mActivity || !checkDeviceHasNavigationBar()) {
            return;
        }

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            mActivity.getContentResolver().registerContentObserver(Settings.System.getUriFor
                    (mDeviceInfo), true, mNavigationBarObserver);
        } else {
            mActivity.getContentResolver().registerContentObserver(Settings.Global.getUriFor
                    (mDeviceInfo), true, mNavigationBarObserver);
        }
    }

  private ContentObserver mNavigationBarObserver = new ContentObserver(new Handler()) {
        @Override
        public void onChange(boolean selfChange) {
            if (null == mActivity) {
                return;
            }
            resetVideoHeightByNavigation(checkNavigation());
        }
    };

當(dāng)然抵代,我們注冊(cè)也不是說所有手機(jī)都注冊(cè)腾节,非全面屏的手機(jī)不用注冊(cè),所以需要判斷一下,但是google 官方提供的檢測(cè)手機(jī)是否有NavigationBar 的方法需要在9.0之后才能用(不是很明白為什么設(shè)置 NavigationBar顏色的方法早就有了案腺,但是檢測(cè)的方法要現(xiàn)在才出╮(╯_╰)╭)庆冕,所以我們只能另辟蹊徑了。
我這里是用檢測(cè)手機(jī)是否存在物理按鍵的方式來反向判斷是否存在虛擬鍵的劈榨,因?yàn)槿嫫恋亩x就是去除物理按鍵访递,替換為虛擬鍵。經(jīng)檢測(cè)同辣,目前在紅米6 pro 上檢測(cè)不準(zhǔn)確拷姿,尷尬。旱函。响巢。代碼如下:

    /**
     * 檢查設(shè)備是否有虛擬鍵
     *
     * @return
     */
    public boolean checkDeviceHasNavigationBar() {
        //通過判斷設(shè)備是否有返回鍵、菜單鍵(不是虛擬鍵,是手機(jī)屏幕外的按鍵)來確定是否有navigation bar
        boolean hasMenuKey = ViewConfiguration.get(mActivity)
                .hasPermanentMenuKey();
        boolean hasBackKey = KeyCharacterMap
                .deviceHasKey(KeyEvent.KEYCODE_BACK);

        if (!hasMenuKey && !hasBackKey) {
            // 做任何你需要做的,這個(gè)設(shè)備有一個(gè)導(dǎo)航欄
            return true;
        }
        return false;
    }

注冊(cè)完成之后棒妨,當(dāng)觸發(fā) onChange 回調(diào)時(shí)踪古,我們就可以根據(jù)當(dāng)前是否展示了虛擬鍵盤來做對(duì)應(yīng)的處理了。原理同樣是檢查settings數(shù)據(jù)庫中字段的變化券腔,但是當(dāng)你去之前的表中檢查時(shí)你會(huì)發(fā)現(xiàn)伏穆,在 VIVO 和 OPPO 的手機(jī)上永遠(yuǎn)返回0!7兹摇枕扫!


呵呵

最后終于查到,是 VIVO 和 OPPO 又移到 Secure 表中H杩Q糖啤!什么?你問我那為什么注冊(cè)的時(shí)候能成功商叹?我只能說燕刻,不造啊╮(╯_╰)╭


vivo oppo

獲取當(dāng)前虛擬鍵是否展示的方法:

    /**
     * 是否展示了 navigationbar
     *
     * @return
     */
    private boolean checkNavigation() {
        int navigationBarIsMin = 0;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            navigationBarIsMin = Settings.System.getInt(mActivity.getContentResolver(),
                    mDeviceInfo, 0);
        } else {
            if (Build.BRAND.equalsIgnoreCase("VIVO") || Build.BRAND.equalsIgnoreCase("OPPO")) {
                navigationBarIsMin = Settings.Secure.getInt(mActivity.getContentResolver(),
                        mDeviceInfo, 0);
            } else {
                navigationBarIsMin = Settings.Global.getInt(mActivity.getContentResolver(),
                        mDeviceInfo, 0);
            }
        }
        return navigationBarIsMin != 1;
    }

最后附上獲取虛擬鍵高度的方法:

    /**
     * 獲取虛擬鍵的高度
     *
     * @return
     */
    public int getNavigationBarHeight() {
        Resources resources = mActivity.getResources();
        int resourceId = resources.getIdentifier("navigation_bar_height",
                "dimen", "android");
        //獲取NavigationBar的高度
        int height = resources.getDimensionPixelSize(resourceId);
        return height;
    }

沒錯(cuò),你猜對(duì)了剖笙!這個(gè)方法在魅族pro6上有問題!明明是一個(gè)沒有虛擬鍵的手機(jī)请唱,結(jié)果人家非的給你返回了一個(gè)高度出來C诌洹!十绑!就問你牛不牛>壑痢!


魅族

總結(jié):以上方法還需更多的驗(yàn)證和完善本橙,而且該方法均是沒考慮劉海屏的情況下扳躬。別急,我已經(jīng)看見產(chǎn)品大佬已經(jīng)拿著需求向我走來了,祝我平安~


我還能寫
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末贷币,一起剝皮案震驚了整個(gè)濱河市击胜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌役纹,老刑警劉巖偶摔,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異促脉,居然都是意外死亡辰斋,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門瘸味,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宫仗,“玉大人,你說我怎么就攤上這事旁仿∶淌玻” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵丁逝,是天一觀的道長汁胆。 經(jīng)常有香客問我,道長霜幼,這世上最難降的妖魔是什么嫩码? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮罪既,結(jié)果婚禮上铸题,老公的妹妹穿的比我還像新娘。我一直安慰自己琢感,他們只是感情好丢间,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著驹针,像睡著了一般烘挫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上柬甥,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天饮六,我揣著相機(jī)與錄音,去河邊找鬼苛蒲。 笑死卤橄,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的臂外。 我是一名探鬼主播窟扑,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼喇颁,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了嚎货?” 一聲冷哼從身側(cè)響起橘霎,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎厂抖,沒想到半個(gè)月后茎毁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忱辅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年七蜘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片墙懂。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡橡卤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出损搬,到底是詐尸還是另有隱情碧库,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布巧勤,位于F島的核電站嵌灰,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏颅悉。R本人自食惡果不足惜沽瞭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望剩瓶。 院中可真熱鬧驹溃,春花似錦、人聲如沸延曙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枝缔。三九已至布疙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間魂仍,已是汗流浹背拐辽。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留擦酌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓菠劝,卻偏偏與公主長得像赊舶,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

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

  • 1笼平、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫組件 SD...
    陽明先生_x閱讀 15,968評(píng)論 3 119
  • 水果是我們?nèi)粘I罱?jīng)常接觸,物美價(jià)廉而又健康誘人的食品夺英,它多種艷麗的顏色和各種獨(dú)特的形狀晌涕,加上豐富的想象力和細(xì)致巧...
    齊梅齊閱讀 2,294評(píng)論 25 53
  • 干涸身體內(nèi)的太陽總不落山 開始憎恨黑不見底的明天 往事在房間里亂了位置 拉著松弛的眼瞼不愿放手 蹣跚的夢(mèng)被半夜驚醒...
    野馬王閱讀 383評(píng)論 9 13
  • 一直一直我都很迷茫自己是一個(gè)怎樣的人 自己是以一個(gè)怎樣的角色在這個(gè)社會(huì)中生存。痛悯。 自己想要什么余黎,能做什么 以后自己...
    Lin小白閱讀 566評(píng)論 0 0
  • 文、圖/江南海北的雪 最近看到一本書《驢行北京》载萌,這是戶外徒步的親身體驗(yàn)之作惧财,是學(xué)者行者的跨界力作!也是第一本以驢...
    江南海北的雪閱讀 259評(píng)論 1 2