一、概述

在项目中,测试发现在一些华为手机的屏幕适配上出现了问题,主要是因为华为Mate等一些系列的手机有一个虚拟按键的设计.当这些虚拟按键由用户手势滑出,或默认显示的话,就会遮挡我们本身的应用布局.比如欢迎界面过后是四个Fragment,那么底部的四个tab就会被虚拟的导航栏遮住,非常难看.

当然,欢迎页的图片适配也同样会出现问题.
Google后得出第一个问题的解决方案.第二个图片的问题则用自己摸索的方式解决,当然也非常简单.

二、布局由于虚拟按键导致导航栏顶上去的解决方法

在我们的项目中加载Fragment的MainActivity,以及其他一般的Activity继承的BaseActivity中的onCreate方法中添加如下代码:

if (AndroidWorkaround.checkDeviceHasNavigationBar(this)) {AndroidWorkaround.assistActivity(findViewById(android.R.id.content));
}

其中AndroidWorkaround使我们为了解决该问题而封装的类,也可以看作是一个特定的工具类:

/**
* 解决底部屏幕按键适配
* Created by Mercury on 2016/10/25.
*/
public class AndroidWorkaround {public static void assistActivity(View content) {new AndroidWorkaround(content);}private View mChildOfContent;private int usableHeightPrevious;private ViewGroup.LayoutParams frameLayoutParams;private AndroidWorkaround(View content) {mChildOfContent = content;mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {public void onGlobalLayout() {possiblyResizeChildOfContent();}});frameLayoutParams = mChildOfContent.getLayoutParams();}private void possiblyResizeChildOfContent() {int usableHeightNow = computeUsableHeight();if (usableHeightNow != usableHeightPrevious) {frameLayoutParams.height = usableHeightNow;mChildOfContent.requestLayout();usableHeightPrevious = usableHeightNow;}}private int computeUsableHeight() {Rect r = new Rect();mChildOfContent.getWindowVisibleDisplayFrame(r);return (r.bottom);}public static boolean checkDeviceHasNavigationBar(Context context) {boolean hasNavigationBar = false;Resources rs = context.getResources();int id = rs.getIdentifier("config_showNavigationBar", "bool", "android");if (id > 0) {hasNavigationBar = rs.getBoolean(id);}try {Class systemPropertiesClass = Class.forName("android.os.SystemProperties");Method m = systemPropertiesClass.getMethod("get", String.class);String navBarOverride = (String) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys");if ("1".equals(navBarOverride)) {hasNavigationBar = false;} else if ("0".equals(navBarOverride)) {hasNavigationBar = true;}} catch (Exception e) {}return hasNavigationBar;}}

重新测试,发现无论是否弹出虚拟按键,都不会再次遮挡tab按钮。

三、原理

上面的代码需要在setContentView后面执行。其最初的解决方案是stackoverflow上有人为了适配软键盘在全屏下的布局问题。
开始先判断该设备上是否存在导航栏。为什么用findViewById(android.R.id.content)呢?因为android.R.id.content这个id代表的就是所在页面的根布局,而并不需要特别指定一个id给该布局。可以通过调用系统API返回的结果,也可以通过判断该手机是否为华为手机,操作系统属于哪种类型来来判断。
一旦确定该设备存在导航栏,将对该布局进行重新测量。首先mChildOfContent得到其视图树,对全局高度实现监听。

OnGlobalLayoutListener 是ViewTreeObserver的内部类,当一个视图树的布局发生改变时,可以被ViewTreeObserver监听到,这是一个注册监听视图树的观察者(observer),在视图树的全局事件改变时得到通知。ViewTreeObserver不能直接实例化,而是通过getViewTreeObserver()获得。

接着得到视图目前可用的总高度,将其赋值给mChildOfContent的布局高度。调用requestLayout,让mChildOfContent要求自己的parent view对自己重新设置位置。

四、全屏图片的适配

解决了布局的问题,再来看欢迎页启动时候全屏图片的适配问题。发现该方法对于图片不适用。如下图,当虚拟按键弹出时,图片照样被遮挡了底部的一小部分。

如果隐藏虚拟按键,图片大小恢复正常

仔细想想,对于一个ImageView直接占据一个layout的情况,是没有必要再去写一些代码进行适配的。到布局里一看,发现ImageView的属性 android:scaleType=”centerCrop”
将其改为 android:scaleType=”fitXY”就可以解决了。这样图片可能高度会随着虚拟键的弹出而压缩,但是很好的适配了布局高度的变化而不会被遮挡。

关于scaleType的详细介绍,留待其他文章里再探讨。

界面适配华为手机的虚拟按键的解决方案相关推荐

  1. Android:解决华为手机隐藏虚拟按键Activity被重新创建的问题

    解决华为手机隐藏虚拟按键Activity被重新创建的问题 问题描述 解决方法 分析 问题描述 在华为手机P9上 屏幕底部虚拟按键用户可以随时隐藏或显示,在改变后 返回上一页,会导致页面重新创建,页面操 ...

  2. 解决输入法遮挡布局和华为手机底部虚拟按键遮挡底部界面的方法

    先上最终的代码: public class AndroidWorkaround {public static void assistActivity(View content) {new Androi ...

  3. 解决华为手机隐藏虚拟按键Activity被重启的问题

    引言 最近技术群里面的妹纸说:在华为手机上开发应用的时候,隐藏底部的虚拟按键Activity会被重启的问题,并且找不到问题所在,于是查查资料,发现问题解决起来蛮简单的. 问题描述 一开始觉得应该是代码 ...

  4. 解决华为手机隐藏虚拟按键Activity被重新创建的问题

    把Activity的生命周期全部打印出来,确定隐藏或显示虚拟按键时,确实导致了Activity重建 然后在onCreate方法中 Configuration configuration = getRe ...

  5. android dialog隐藏虚拟按键,关于此框架在BottomSheetDialogFragment使用时,华为手机底部虚拟按键弹出与隐藏时输入框位置不贴键盘...

    我这边试过还是不行,而且我们ui是要dialog不全屏的,下面附上代码 public void onStart() { super.onStart(); Dialog dialog = getDial ...

  6. Android启动页,引导页适配华为手机(虚拟按键)显示问题

    前言 看到我这篇文章的同学肯定会质疑我开发的能力,我遇到的问题总是很奇怪,估计真的跟我的开发能力有关系~~~,最近公司的B端项目要上线了,UI妹子昨天给做了几张引导页与一张启动页,原来没有仔细观察过图 ...

  7. 隐藏与显示华为等有虚拟按键手机的虚拟按键

    关于手机虚拟按键的坑 首先吐槽一下虚拟按键,这个真的是没有卵用,个人觉得体验效果也差,不知道为什么华为会坚持使用.最近公司项目需用用到视频监控,在做视频播放全屏切换时,华为等有虚拟按键的手机,卡得我欲 ...

  8. 关于Android适配华为等带有底部虚拟按键的解决方案

    关于Android适配华为等带有底部虚拟按键的解决方案 参考文章: (1)关于Android适配华为等带有底部虚拟按键的解决方案 (2)https://www.cnblogs.com/dhcn/p/7 ...

  9. android 隐藏手机底部虚拟按键

    今天,简单讲讲android如何隐藏手机下面的虚拟按键. 其实,自己在做界面适配时,老是发现了华为手机存在适配的问题,主要就是华为手机有一个底部的虚拟按键占用了界面的部分空间,所以在网上搜索了如何隐藏 ...

最新文章

  1. window mobile 5.0截获来电
  2. 【Python】条件及循环语句
  3. 差分能量分析介绍(二)
  4. 世界最小晶体管问世 栅极长度仅一纳米
  5. Spring集成–配置Web服务客户端超时
  6. LeetCode 79. Word Search
  7. LeetCode7——Reverse Integer(将一个整数反转,注意溢出的处理)
  8. 学习OpenCV——ORB简化版Location加速版
  9. javaweb成长之路:SSM框架搭建
  10. java和c的反汇编_JAVAP -C反汇编指令的学习(转载)
  11. Linux /etc/login.defs配置文件
  12. VHDL实现矩阵键盘
  13. Vue3 源码阅读(3):响应式系统 —— 重置 effect 的依赖收集、嵌套的 effect、effect 调度执行
  14. notification 发送通知后顶栏的小图标不对,为纯白色而不是设置的smallIcon 的原因
  15. Camtasia Studio 8
  16. 怀旧服一区和五区服务器位置,魔兽怀旧服战场分组怎么看?怀旧服战场分组一区五区怎么分的?...
  17. Python关于reverse()和reversed()的用法和区别-列表反转
  18. 第4章 学习Shader所需的数学基础(上)(坐标系、点和矢量)
  19. 【CHATGPT-3.5】如何使用ChatGPT的同时并学习记忆
  20. Linux —— 时间问题(GMT,UTC,DST,CST,CET表示什么、UTC与CST之间的转换)

热门文章

  1. 有种速度让你望尘莫及 | 手机QQ及Qzone速度优化实践
  2. 使用jquery ajax 实现用户的用户名注册验证,如果该用户已存在则提示该用户已存在
  3. python用户价值分析
  4. netgear 网件R6250路由 从OpenWrt或者DD-WRT系统恢复到默认系统 适合小白
  5. OSChina 周日乱弹 ——我18岁了都没睡过男人
  6. 什么是PowerShell,一起来看看自动化的历史发展阶段
  7. 无人叉车市场现状与发展趋势分析|无人叉车专题(一)
  8. Found conflicts! Looking for incompatible packages. This can take several minutes. Press CTRL-C
  9. 中秋节快乐 | 9月21日 星期二 | 天舟三号货运飞船发射成功;理想汽车下调第三季度交付量预期;凯德集团业务重组完成...
  10. Elasticsearch:验证 Elasticsearch Docker 镜像并安装 Elasticsearch