寫之前先吐槽下自己碍沐,工作了這么多年辙浑,終于能靜下心來寫博客了
最近公司有個(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í)候能成功商叹?我只能說燕刻,不造啊╮(╯_╰)╭
獲取當(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)拿著需求向我走來了,祝我平安~