当 Android 手机设备进行横屏状态时,其虚拟按键的位置在不同版本上位置可能不同。

问题描述

应用里面为了实现全局的右滑返回效果而引入了一个 SwipeBack 库 (GitHub - SwipeBackLayout),然后将基类的 Activity 直接继承自 SwipeBackActivity。这之后就发现在 Android 7.0 的手机上横屏时,整个布局都向屏幕左侧移动了一些,导致左边被虚拟按键给挡住了。效果如下图:

经反复测试后发现,只有在 Android 7.0 及以上版本的手机设备上,将设备顺时针旋转 90 度后才会出现该问题。如果是逆时针旋转、6.0 及以下设备、或者平板设备都不会有这个问题。这是因为从 Android 7.0 开始,虚拟按键的位置在横屏状态下发生了变化。在以前版本的手机设备中,横屏时的虚拟按键总是在屏幕右侧,而 Android 7.0 将虚拟按键在横屏状态下的位置改为了“总是接近设备底部”。就是说,如果手机顺时针旋转 90 度,此时设备底部在左侧,虚拟按键也就随之出现在左侧。而如果是逆时针旋转 90 度则在右侧,跟以前一样。

见下图,上面是 Android 6.0 设备,下图是 7.0。

此外,平板设备上因为虚拟按键总在屏幕底部,所以也不存在该问题。

解决方案

这个 SwipeBackActivity 的实现方式是在 Activity.onPostCreate 的时候,获取布局根层的 DecorView,将其子 view 作为 swipeBackLayout 的子 view,然后再将 swipeBackLayout 插进 DecorView 中。从而做到在不修改 layout 文件的情况下将 swipeBackLayout 变成根 view。从这个实现方式上很显然可以猜到,这个替换的过程导致了布局的异常。因此要解决该问题,容易想到的一个方式就是直接在每个 acitivty 的布局里面写上 swipeBackLayout,不使用这种 onPostCreate 时强行修改根布局的方式即可。但是那样的话要修改的地方太多,我们还是希望在原先的基础上做尽量少的改动将问题解决。因此我们考虑在 SwipeBackLayout 上将布局移动到正确的位置。

首先是考虑如何获取虚拟按键当前在屏幕上的位置,在 AndroidXRef 上从 Android 源码一层层跟进去之后发现实现过于复杂,因此直接用现有的信息进行条件判断: Android 7.0 以上、手机设备,顺时针旋转 90 度。

知道了虚拟按键的位置之后就要计算虚拟按键的高度。我们可以通过 WindowManager 中 getdefaultDisplay 之后的 getRealSize 和 getSize 这两个方法进行计算。

最后主要的代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66@Override

protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

mInLayout = true;

if (mContentView != null) {

mContentLeft = getLeftPadding(mActivity);

mContentView.layout(mContentLeft, mContentTop,

mContentLeft + mContentView.getMeasuredWidth(),

mContentTop + mContentView.getMeasuredHeight());

}

mInLayout = false;

}

private int getLeftPadding(Context context) {

// 1. Android Version >= 7.0

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {

return 0;

}

// 2. Is Mobile Phone

if (context.getResources().getConfiguration().smallestScreenWidthDp >= 600) {

return 0;

}

// 3. is 270 rotation

int screenAngle = getScreenRotationAngle(context);

if (screenAngle != Surface.ROTATION_270) {

return 0;

}

// 4. get navigation height

return getNavigationBarHeight(context);

}

public int getNavigationBarHeight(Context context) {

WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

if (wm == null) {

return 0;

}

Display display = wm.getDefaultDisplay();

Point devicePoint = new Point();

display.getRealSize(devicePoint);

Point appPoint = new Point();

display.getSize(appPoint);

if (appPoint.x < devicePoint.x) { // landscape

return devicePoint.x - appPoint.x;

} else if (appPoint.y < devicePoint.y) { // portrait

return devicePoint.y - appPoint.y;

}

return 0;

}

public int getScreenRotationAngle(Context context) {

WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

if (wm == null) {

return Surface.ROTATION_0;

}

Display display = wm.getDefaultDisplay();

return display.getRotation();

}

BTW,设备顺时针旋转 90 度意味着屏幕上的内容要顺时针旋转 270 度,因此上面对于旋转角度的判断是 ROTATION_270 而非 ROTATION_90。

Ref

android8虚拟键布局,Android 虚拟按键在不同版本上的位置问题相关推荐

  1. android 虚拟键 高度,Android获取虚拟按键的高度(适配全面屏)

    在开发过程中,假如我们要从底部弹出一个popwindow,这时候我们需要考虑获取实际显示的虚拟键高度. 期望: 全面屏下 1.1 开启全面屏开关-返回0 1.2 关闭全面屏开关-执行非全面屏下处理方式 ...

  2. android获取按键键值,android中按键的扫描码和键值

    kernel中的按键驱动通过input子系统上报的键值叫做扫描码(ScanCode),对应头文件在 kernel/include/uapi/linux/input.h andorid中的用到的按键才叫 ...

  3. android 虚拟按键挡住布局,Android 虚拟按键遮住了页面内容解决办法

    在启动页的时候华为手机虚拟按键遮挡住了启动页下面的字找了找解决办法,特地记录一下 第一种办法:扩展虚拟按键 //状态栏 @ 顶部getWindow().addFlags(WindowManager.L ...

  4. android 虚拟键背景,Android 设置应用的底部导航栏(虚拟按键)背景颜色

    Android手机机型种类繁多,但是虚拟按键也就是底部的导航栏,不外乎两种设计方式,一种是作为虚拟按键设计到屏幕内部,一种是作为系统按键设计到屏幕外面. 对于按键在屏幕内部的机型,因为虚拟按键也是屏幕 ...

  5. android 虚拟键 高度,Android,获取虚拟键盘的高度

    在很多时候,很多需求下,我们都需要得知键盘的高度啊!实在不能理解为什么安卓不提供这样方便的API.虽然没有很好的监听事件,但是我们还是可以制造一个的.想想虚拟键盘弹起来之后界面发生了什么变化?对的,有 ...

  6. Android 高德地图在华为手机上获取位置信息失败

    昨天遇到一个特别奇怪的bug,华为手机获取高德定位信息失败,调试打印数据后发现 location.getAddress()这个获取值为空,之前一直选择高精度模式,但是获取不到位置信息 //设置定位模式 ...

  7. android华为手机虚拟键,华为手机为何“固执”地保留屏内虚拟按键?答案揭秘!...

    本帖最后由 请称呼我所长 于 2017-9-5 00:33 编辑 0.jpg (39.44 KB, 下载次数: 158) 2017-9-3 15:12 上传 最in科技所,好玩的.新鲜的科技资讯都在这 ...

  8. Android 虚拟分区详解(二) 虚拟分区布局

    文章目录 0. 导读 1. Android 传统 A/B 分区和动态分区布局 2. Android 虚拟分区布局 3. 虚拟分区的思考 2.1 分区只有一套,如何实现 A/B 系统特性? 2.2 部分 ...

  9. Android 默认按键音开关

    android 默认按键音开关的值存储位置在 frameworks/base/packages/SettingsProvider/res/values/defaults.xml , <!-- D ...

最新文章

  1. node.js 多个异步过程判断执行是否完成
  2. 使用Qt作窗口截屏(含源码)
  3. leetcode-121-买卖股票的最佳时机
  4. Regarding empty field check in business document save
  5. [软技能] png-8和png-24有什么区别?
  6. 安装Windows 2003 域控制器
  7. 跑深度学习在Linux服务器上常用操作(ssh, screen, tensorboard, jupyter-notebook)
  8. scrum master_从Scrum Master到工程副总裁:职称为何重要
  9. [SHELL]监控LINUX目录文件变化
  10. 【算法】剑指 Offer 59 - II. 队列的最大值
  11. I.MX6 dhcpcd 需要指定网卡
  12. lsb_release -a 查询Linux系统版本
  13. 这样配置win10亲测不错
  14. cookie的工作原理、cookie的重要性
  15. [网络工程师]-路由协议-IGRP协议
  16. 计算机考研时间计划表,【考研复习计划】_这里有最详细的考研复习计划时间表...
  17. 数据结构与算法入门教程(C语言实现版)
  18. Java EXCEL 表格导入导出(带下拉选-带VLOOKUP函数封装)
  19. win10右键刷新卡顿解决方案
  20. userdel: user * is currently used by process 1278

热门文章

  1. GYM 101173 K.Key Knocking(构造)
  2. Excel隔行插入空白行
  3. 医院计算机专业年薪,说一些我朋友真实的深圳公立三甲医院编制收入
  4. 计算机辅助设计在口腔医学中的应用,椅旁CAD/CAM技术在口腔修复中的应用
  5. MySQL 删除大量数据
  6. 计算机快捷键如何移动到桌面,如何设置显示桌面快捷键 设置显示桌面快捷键方法【图文】...
  7. python xlrdxlwt应用 以文本形式存储数字 数字前补零
  8. 【在线电子书转换】云展网教程 | 如何设置电子书的翻页速度?
  9. csdn邻家割草_如何维护割草机,使其永远持续(几乎)
  10. 数学智力题 武士数独题目_最新智力题大全及答案-各种最新IQ题目推荐-第1595页-33IQ...