适配Android 华为等底部虚拟键(转载自笑慢)

在app开发中有很多项目使用底部tab+ ViewPager + fragment 的框架,那么这个时候如果app安装在底部带有虚拟键的设备上的话,会产生设备底部的虚拟键遮挡app底部tab的情况,这个时候对app的外观和功能的使用都产生了很大的影响,下边我们对此情况进行适配。

1、首先我们进行工具类的封装,主要思路是addOnGlobalLayoutListener全局监听视图的变化(onGlobalLayoutListener是viewTreeObserver的内部类,当视图变化时onGlobalLayoutListener可以监听到),那么当视图的高度发生变化时,就对这个视图重新布局,使视图不被遮挡。

 
  1. import android.content.Context;

  2. import android.content.res.Resources;

  3. import android.graphics.Rect;

  4. import android.view.View;

  5. import android.view.ViewGroup;

  6. import android.view.ViewTreeObserver;

  7.  
  8. import java.lang.reflect.Method;

  9.  
  10. public class NavigationBarUtil {

  11. public static void initActivity(View content) {

  12. new NavigationBarUtil(content);

  13. }

  14.  
  15. private View mObserved;//被监听的视图

  16. private int usableHeightView;//视图变化前的可用高度

  17. private ViewGroup.LayoutParams layoutParams;

  18.  
  19. private NavigationBarUtil(View content) {

  20. mObserved = content;

  21. //给View添加全局的布局监听器监听视图的变化

  22. mObserved.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

  23. public void onGlobalLayout() {

  24. resetViewHeight();

  25. }

  26. });

  27. layoutParams = mObserved.getLayoutParams();

  28. }

  29.  
  30. /**

  31. * 重置视图的高度,使不被底部虚拟键遮挡

  32. */

  33. private void resetViewHeight() {

  34. int usableHeightViewNow = CalculateAvailableHeight();

  35. //比较布局变化前后的View的可用高度

  36. if (usableHeightViewNow != usableHeightView) {

  37. //如果两次高度不一致

  38. //将当前的View的可用高度设置成View的实际高度

  39. layoutParams.height = usableHeightViewNow;

  40. mObserved.requestLayout();//请求重新布局

  41. usableHeightView = usableHeightViewNow;

  42. }

  43. }

  44.  
  45. /**

  46. * 计算试图高度

  47. * @return

  48. */

  49. private int CalculateAvailableHeight() {

  50. Rect r = new Rect();

  51. mObserved.getWindowVisibleDisplayFrame(r);

  52. return (r.bottom - r.top);//如果不是沉浸状态栏,需要减去顶部高度

  53. // return (r.bottom );//如果是沉浸状态栏

  54. }

  55.  
  56. /**

  57. * 判断底部是否有虚拟键

  58. * @param context

  59. * @return

  60. */

  61. public static boolean hasNavigationBar(Context context) {

  62. boolean hasNavigationBar = false;

  63. Resources rs = context.getResources();

  64. int id = rs.getIdentifier("config_showNavigationBar", "bool", "android");

  65. if (id > 0) {

  66. hasNavigationBar = rs.getBoolean(id);

  67. }

  68. try {

  69. Class systemPropertiesClass = Class.forName("android.os.SystemProperties");

  70. Method m = systemPropertiesClass.getMethod("get", String.class);

  71. String navBarOverride = (String) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys");

  72. if ("1".equals(navBarOverride)) {

  73. hasNavigationBar = false;

  74. } else if ("0".equals(navBarOverride)) {

  75. hasNavigationBar = true;

  76. }

  77. } catch (Exception e) {

  78.  
  79. }

  80. return hasNavigationBar;

  81.  
  82. }

  83.  
  84. }

2、在需要适配的activity 的 onCreate方法中的 super.onCreate(savedInstanceState)之后 调用

 
  1. if(NavigationBarUtil.hasNavigationBar(this)){

  2. NavigationBarUtil.initActivity(findViewById(android.R.id.content));

  3. }

(推荐封装base 这样就可以直接继承base就可以)。

最后的效果就是app底部tab 在设备的虚拟键之上。

猜你喜欢

转载自blog.csdn.net/qq_32138419/article/details/81449784