场景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>
- 1
注意: 你会发现系统报错,这是因为这句话是在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这里就不说了,有兴 ...
随机推荐
-
ThinkPhp5.0模型验证规则
Tp5提供了模型数据规则的验证功能,用于在数据save或者update前验证数据的有效性.Tp5提供校验规则的类为\Think\Validate,默认提供的校验规则可以查看该文件. 在Model文件中 ...
-
Android自定义surfaceView显示多张图片
我自定义了一个surfaceview,我在上面绘制多张图片,让它能够上下方滚显示图片,但是onMeasure()方法在重写的时候遇到了问题,不知道如何设置它的高度, public class MySu ...
-
Linux下通过ODBC连接sqlserver
Linux下通过ODBC连接sqlserver 1.需求: 最近有个需求就是要在linux下连接(可以执行sql语句)sqlserver 2.环境 操作系统: Centos6.5 数据库: ...
-
今天工作中遇到的根据用户id取得产品大类和相关小类的问题
今天做了一个项目,需求是客户登陆后,可以从会员中心发布详细信息(包括联系信息和公司信息),插入到数据库后在将来生成一个公司页面模板,一般的产品大类+小类 用repeater嵌套就可以了,但是这个涉及到 ...
-
Linux内核和驱动编译常见问题
1.获取内核源码应为 git clone depth=1 不然编译时会报错 2.有些RTL188CUS网卡与wpa_supplicant兼容有问题 更新wpasupplicant或许能解决 这里用i ...
-
Spring设计模式_策略模式/其他
策略模式特性 1.执行最终结果一样 2.执行过程和执行逻辑不一样 3.使用同一接口 达到目的就可以了 Git地址 https://github.com/wujiachengSH/WjcStrategy ...
-
idea crack
ThisCrackLicenseId-{ “licenseId”:”11011”, “licenseeName”:”Wechat”, “assigneeName”:”tree-deep-see-dee ...
-
shell编程 学好内功(一)
shell 背景 什么是shell编程 高大上的解释,往往让人摸不住头脑.一句话概括就是:shell编程就是对一堆Linux命令的逻辑化处理. 为什么要会shell编程 举个简单的例子,我们做java ...
-
[LeetCode] 系统刷题3_Binary search
可以参考 [LeetCode] questions conclusion_ Binary Search
- keil mdk5安装