问题
安卓机型太多适配比较麻烦,这里来讲讲部分手机有的底部虚拟导航按钮适配问题,我遇到有虚拟底部导航栏的手机就有:华为,索尼,OPPO……。
底部导航栏适配需要解决的以下几个问题:
- 哪些机型有底部虚拟导航栏;
- 底部导航栏的高度是多少;
- 针对有底部导航对布局高度进行调整;
是否显示底部导航栏
SDK在版本17之后增加了一个获取Window显示区域分辨率和实际分辨率大小的两个方法:
Display display = act.getWindowManager().getDefaultDisplay(); display.getSize(size); display.getRealSize(realSize);
realSize.y其实包含了虚拟导航栏的高度,如果两个size的y坐标不想等,那么就说明有虚拟底部导航栏。
在低版本里面我们就只能通过,设备是否有永久菜单或者有返回键来判断,如果在设备上有了物理返回按钮或菜单就不需要再添加虚拟的导航栏,如果两个都有,那么这个手机厂商估计也倒闭了,直接代码:
boolean menu = ViewConfiguration.get(act).hasPermanentMenuKey();
boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
只要menu或者back有一个就表示有物理导航栏,没有虚拟底部导航栏了。
底部导航栏的高度
获取底部导航栏高度,在系统的资源里面有这个高度的值,我们通过获取系统资源数据就OK:
int resourceId = context.getResources().getIdentifier(“navigation_bar_height”, “dimen”, “android”);
context.getResources().getDimensionPixelSize(resourceId);
根据导航栏调整布局的高度
调整布局高度根据需求作出响应的调整就OK。
代码
最后把第1,2的代码逻辑整理成工具方法,大家可以直接拷贝使用:
/**
* 判断底部导航栏是否显示
*
* @param act
* @return
*/
public static boolean isNavigationBarShow(Activity act) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
Display display = act.getWindowManager().getDefaultDisplay();
Point size = new Point();
Point realSize = new Point();
display.getSize(size);
display.getRealSize(realSize);
return realSize.y != size.y;
} else {
boolean menu = ViewConfiguration.get(act).hasPermanentMenuKey();
boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
if (menu || back) {
return false;
} else {
return true;
}
}
}
/**
* 如果有底部导航栏 获取底部导航栏高度
* @param context
* @return
*/
public static int getBottomNavigatorHeight(Context context) {
int rid = context.getResources().getIdentifier("config_showNavigationBar", "bool", "android");
if (0 != rid) {
int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
return context.getResources().getDimensionPixelSize(resourceId);
}
return 0;
}