Android 适配底部返回键等虚拟键盘的完美解决方案
这个问题来来回回困扰了我很久,一直没能妥善解决。
场景1:华为手机遮挡了屏幕底部。
场景2:进入应用时,虚拟键自动缩回,留下空白区域。
需求:
需要安卓能自适应底部虚拟按键,用户隐藏虚拟按键时应用要占满整个屏幕,当用户启用虚拟键时,应用能往上收缩,等于是被底部虚拟按键顶上来。
需求很简单,实现起来却困难重重。
完美解决方案:
解释一下下面的代码,就是监听某个视图的变化,当可以看见的高度发生变化时,就对这个视图重新布局,保证视图不会被遮挡,也不会浪费屏幕空间。这一点尤其可用在像华为手机等可以隐藏和显示虚拟键盘上导致屏幕变化的手机上。
- 首先添加工具类AndroidBug54971Workaround
package com.xxxx.xxxx; import android.graphics.Rect;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver; /**
* Created by win7 on 2016/12/14.
*/ public class AndroidBug54971Workaround {
// For more information, see https://code.google.com/p/android/issues/detail?id=5497
// To use this class, simply invoke assistActivity() on an Activity that already has its content view set. /**
* 关联要监听的视图
*
* @param viewObserving
*/
public static void assistActivity(View viewObserving) {
new AndroidBug54971Workaround(viewObserving);
} private View mViewObserved;//被监听的视图
private int usableHeightPrevious;//视图变化前的可用高度
private ViewGroup.LayoutParams frameLayoutParams; private AndroidBug54971Workaround(View viewObserving) {
mViewObserved = viewObserving;
//给View添加全局的布局监听器
mViewObserved.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
resetLayoutByUsableHeight(computeUsableHeight());
}
});
frameLayoutParams = mViewObserved.getLayoutParams();
} private void resetLayoutByUsableHeight(int usableHeightNow) {
//比较布局变化前后的View的可用高度
if (usableHeightNow != usableHeightPrevious) {
//如果两次高度不一致
//将当前的View的可用高度设置成View的实际高度
frameLayoutParams.height = usableHeightNow;
mViewObserved.requestLayout();//请求重新布局
usableHeightPrevious = usableHeightNow;
}
} /**
* 计算视图可视高度
*
* @return
*/
private int computeUsableHeight() {
Rect r = new Rect();
mViewObserved.getWindowVisibleDisplayFrame(r);
return (r.bottom - r.top);
}
}
- 然后在你需要解决这个问题的Activity的onCreate方法的setContentView(R.layout.content_frame);后面添加上
setContentView(R.layout.content_frame);
AndroidBug54971Workaround.assistActivity(findViewById(android.R.id.content));
如果你看的懂代码,你肯定知道assistActivity方法里放入的View是你 要调整高度的视图。
其他不完美方案:或多或少在某些情况上会起不到作用
我一种方法:
android:fitsSystemWindows=”true”
这句话写在layout的根目录下,看名字就知道是自适应系统窗口。估计能解决很大一部分手机了,可是在同事的nexus 4下并没有什么用。
第二种方法:
我去掉了每个布局的android:fitsSystemWindows=”true”
在style文件中添加了这句话。
<item name="android:windowTranslucentNavigation">false</item>
注意: 你会发现系统报错,这是因为这句话是在API-19后才有的,所以你可以复制你的style文件,把它放到API-19的文件夹下。这样的用途就是如果手机大于等于API19,就会用API-19的文件夹下的内容。否则用原来的style文件。你在API19文件夹下的style文件的根主题中添加上面这句话就OK啦。
本来我以为是完美解决了我的问题。可是被打脸了。刚进入App时会出现上面的场景2的情况。
我一看MainActivity中的onCreate方法的setContentView(R.layout.xxxx);之前有下面的代码
//控制底部虚拟键盘
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
// | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
| View.SYSTEM_UI_FLAG_IMMERSIVE);
估计是这个项目以前的仁兄为了解决这个问题添加的。
经过多次调试,我添加了一句话
//控制底部虚拟键盘
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
// | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
| View.SYSTEM_UI_FLAG_IMMERSIVE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
场景2的情况解决了。这是在虚拟键一直存在的情况下没有问题了,因为nexus不能手动隐藏虚拟键盘,所以我也不清楚是否能在华为等手机上正常运行。TODO。
另外如果想要一直隐藏虚拟键盘,点击屏幕也不会出现的话,将上面的代码换成:
//让虚拟键盘一直不显示
Window window = getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION|View.SYSTEM_UI_FLAG_IMMERSIVE;
window.setAttributes(params);
Android 适配底部返回键等虚拟键盘的完美解决方案的更多相关文章
- Android适配底部返回键等虚拟键盘的完美解决方案
这个问题来来回回困扰了我很久,一直没能妥善解决. 场景1:华为手机遮挡了屏幕底部. 场景2:进入应用时,虚拟键自动缩回,留下空白区域. 需求: 需要安卓能自适应底部虚拟按键,用户隐藏虚拟按键时应用要占 ...
- Android监听返回键、Home键+再按一次返回键退出应用
Android监听返回键需重写onKeyDown()方法 Home键keyCode==KeyEvent.KEYCODE_HOME @Override public boolean onKeyDown( ...
- android 监听返回键
android监听返回键 public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE ...
- android点击返回键,如何做到不destory当前activity,只是stop。重新返回该activity的 时候可以直接使用,不需要创建新的activity实例
问题描述,如题目: android点击返回键,顺序执行 pause,stop,destory. 以至于想重新进入这个activity的时候还要重新执行onCreate()方法,那么如何解决不再重新执行 ...
- android 点击返回键退出程序的方法
android 点击返回键退出程序的方法 第一种: 再按一次返回键退出程序 private long exitTime = 0; @Override public boolean onKeyDown( ...
- Android应用中返回键的监听及处理
MainActivity: package com.testnbackpressed; import android.os.Bundle; import android.view.KeyEvent ...
- Android 监听返回键、HOME键
拦截返回键,HOME键,继承BaseActivity即可 import android.app.Activity; import android.content.BroadcastReceiver; ...
- cocos2d-x在android中响应返回键编译报错的bug分析
先看一段代码如何在Android中加入返回按键的响应 <span style="font-size:18px;">自己派生CCKeypadDelegate的子类,然后注 ...
- 从网页监听Android设备的返回键
最近搞Android项目的时候,遇到一个比较蛋疼的需求,需要从Client App调用系统浏览器打开一个页面,进行杂七杂八的一些交互之后,返回到App.如何打开浏览器和如何返回App这里就不说了,有兴 ...
随机推荐
- Vijos1221:神秘的配方
背景 每天中午的下课铃一响,浙江镇海中学的同学们都会冲出学校来附近的小饭馆吃饭,刹那间天昏地暗,飞砂走石,家家餐馆内都是一片黑压压的人 .馄饨店.饺子馆,在学校附近开一家红一家.身为镇海中学信息中心首 ...
- SpringMVC之二:配置 Spring MVC
Servlet 3.0规范在2009年12月份就发布了,因此很有可能你会将应用部署到支持Servlet 3.0的Servlet容器之中,如tomcat7.0及以上.在Servlet 3 规范中,可以使 ...
- asn编译常见报错
TypeError: unsupported operand type(s) for -: 'str' and 'int' 可能是该用列表的地方没用列表. 1. ’-‘不支持,需改为'_' asn1t ...
- EIP权限工作流升级说明-2019/5/23
增加mysql版本在线预览地址:http://www.eipflow.com:3000/
- E20190420-hm
impact n. 巨大影响; 强大作用; 撞击; 冲撞; 冲击力; v. (对某事物) 有影响,有作用; 冲击; 撞击; incident n. 发生的事情(尤指不寻常的或讨厌的); 严 ...
- 在GitHub上上传项目(转载)
今天准备在GitHub第一次上传自己的项目,发现过程并不是太简单,在网上找了一个博客,写的很详细,结合着他的讲解成功上传了自己的项目. 结合着他的步骤和自己遇到的问题,做一个梳理,以便以后使用.(原博 ...
- CentOS 6.5 安装Clang 3.5.0
来自引用: http://www.cnblogs.com/dudu/p/4294374.html 编译llvm几乎耗费了1个小时-.. 编译CoreCLR需要Clang 3.5,而CentOS上安装的 ...
- Codevs 1257 打砖块
1257 打砖块 http://codevs.cn/problem/1257/ 题目描述 Description 在一个凹槽中放置了n层砖块,最上面的一层有n块砖,第二层有n-1块,……最下面一层仅有 ...
- ERROR 1366 (HY000): Incorrect string value: '\xB3\xA4\xC9\xB3' for column
在用以下方法之前,请先执行下面命令查看. show variables like 'character%'; ——查看所有编码方式 show create table table_name; — ...
- C# 数据库连接字符串拼接
string connectionString = string.Format(@"Data Source={0};User ID={1};Password={2};Initial Cata ...