Android獲取底部導(dǎo)航部分機型(華為nova凭舶,小米8等)出現(xiàn)了沒有底部導(dǎo)航欄,但是卻檢測到了爱沟,手動給視圖加高度的UI就出現(xiàn)了問題帅霜,下方多了一部分空白,于是查找新的方法呼伸。
檢測導(dǎo)航欄
先看原來使用的方法身冀,Android想要獲取底部虛擬NavigationBar的高度,需要先檢測該手機有無底部導(dǎo)航括享,示例代碼如下:
/**
* 檢查是否存在虛擬按鍵欄
*/
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private static boolean hasNavBar(Context context) {
Resources res = context.getResources();
int resourceId = res.getIdentifier("config_showNavigationBar", "bool", "android");
if (resourceId != 0) {
boolean hasNav = res.getBoolean(resourceId);
String sNavBarOverride = getNavBarOverride();
if ("1".equals(sNavBarOverride)) {
hasNav = false;
} else if ("0".equals(sNavBarOverride)) {
hasNav = true;
}
return hasNav;
} else {
return !ViewConfiguration.get(context).hasPermanentMenuKey();
}
}
/**
* 判斷虛擬按鍵欄是否重寫
*/
private static String getNavBarOverride() {
String sNavBarOverride = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
Class c = Class.forName("android.os.SystemProperties");
Method m = c.getDeclaredMethod("get", String.class);
m.setAccessible(true);
sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");
} catch (Exception e) {
Timber.e(e.toString());
}
}
return sNavBarOverride;
}
獲取導(dǎo)航高度
如果返回為true才可以獲取底部導(dǎo)航的高度搂根,下邊是獲取底部導(dǎo)航高度的代碼:
/**
* 獲取虛擬按鍵的高度
*/
public static int getNavigationBarHeight(Activity activity) {
int result = 0;
if (hasNavBar(activity)) {
Resources res = activity.getResources();
int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
result = res.getDimensionPixelSize(resourceId);
}
}
Timber.d("NavigationBarHeight = " + result);
return result;
}
但是后邊測試過程中出現(xiàn)了問題,有些頁面橫豎屏切換動態(tài)加了這個高度铃辖,在部分手機上出現(xiàn)了剩愧,沒有底部導(dǎo)航,但是檢測到了的情況娇斩,導(dǎo)致整個布局下方出現(xiàn)了白條仁卷,于是開始找如何新的檢測底部導(dǎo)航是否存在的方法。
新方法檢測底部導(dǎo)航是否存在
private static final String NAVIGATION = "navigationBarBackground";
// 該方法需要在View完全被繪制出來之后調(diào)用犬第,否則判斷不了
public static boolean isNavigationBarExist(@NonNull Activity activity) {
ViewGroup vp = (ViewGroup) activity.getWindow().getDecorView();
if (vp != null) {
for (int i = 0; i < vp.getChildCount(); i++) {
vp.getChildAt(i).getContext().getPackageName();
if (vp.getChildAt(i).getId() != NO_ID && NAVIGATION.equals(activity.getResources().getResourceEntryName(vp.getChildAt(i).getId()))) {
return true;
}
}
}
return false;
}
這種方式需要在view加載完成后五督,遍歷所有view,來判斷底部導(dǎo)航是否顯示了瓶殃,比上邊使用getIdentifier獲取的方式更準(zhǔn)確充包,可以適配可以檢測到有,但實際沒有顯示的場景。