快速解决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适配底部返回键等虚拟键盘的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Android优雅的方式解决软键盘遮挡按钮问题

    前言 比如在进行登录的操作中,用户输入完密码之后,肯定是想直接点击登录按钮的.返回键隐藏软键盘这样的体验肯定很糟糕,程序员,遇到问题解决问题. 实现1 xml <ScrollView android:id="@+id/scrollview" android:layout_width="match_parent" android:layout_height="wrap_content" android:fadingEdge="non

  • 基于界面适配华为手机的虚拟按键的解决方法

    一.概述 在项目中,测试发现在一些华为手机的屏幕适配上出现了问题,主要是因为华为Mate等一些系列的手机有一个虚拟按键的设计.当这些虚拟按键由用户手势滑出,或默认显示的话,就会遮挡我们本身的应用布局.比如欢迎界面过后是四个Fragment,那么底部的四个tab就会被虚拟的导航栏遮住,非常难看. 当然,欢迎页的图片适配也同样会出现问题. Google后得出第一个问题的解决方案.第二个图片的问题则用自己摸索的方式解决,当然也非常简单. 二.布局由于虚拟按键导致导航栏顶上去的解决方法 在我们的项目中加

  • Android 隐藏底部虚拟键的两种方法

    方法一  滑动屏幕 可重新显示出来 protected void hideBottomUIMenu() { //隐藏虚拟按键,并且全屏 if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { // lower api View v = this.getWindow().getDecorView(); v.setSystemUiVisibility(View.GONE); } else if (Build.V

  • android虚拟键盘弹出遮挡登陆按钮问题的解决方法

    Android虚拟键盘的弹起会遮挡住部分ui,虽然通过在清单文件中设置,可以随着虚拟键盘的弹出,布局往上推,但是面对登陆界面时,并没有太大的作用,这样就会导致用户体验不好:开发中既然出现了就的解决:先说先解决的思路:获取到屏幕的高度.虚拟键盘的高度,布局的高度,用屏幕的高度减去布局的高度,用高度差和虚拟键盘的高度进行对比:代码实现如下: private LinearLayout logo_layout; private ImageView iv_logo; private int sh; pri

  • 完美解决虚拟按键遮盖底部视图的问题

    Android部分手机会有虚拟按键,而没有实体按键,例如华为系列的手机. 然而在开发过程中,有时候会涉及底部视图的开发,最终的结果却因为虚拟按键的关系,结果底部视图被虚拟按键给遮盖住了. 在这里,分为两种情况,一种是Activity继承普通的Activity,一种是Activity继承AppcompatActivity. 第一种情况的解决方案:(继承普通的Activity) 直接在配置文件Androidmanifest.xml里对相应的Activity设置样式, Theme 如果设置成Theme

  • 快速解决Android适配底部返回键等虚拟键盘的问题

    这个问题来来回回困扰了我很久,一直没能妥善解决. 场景1:华为手机遮挡了屏幕底部. 场景2:进入应用时,虚拟键自动缩回,留下空白区域. 需求: 需要安卓能自适应底部虚拟按键,用户隐藏虚拟按键时应用要占满整个屏幕,当用户启用虚拟键时,应用能往上收缩,等于是被底部虚拟按键顶上来. 需求很简单,实现起来却困难重重. 完美解决方案: 解释一下下面的代码,就是监听某个视图的变化,当可以看见的高度发生变化时,就对这个视图重新布局,保证视图不会被遮挡,也不会浪费屏幕空间.这一点尤其可用在像华为手机等可以隐藏和

  • Android onbackpressed实现返回键的拦截和弹窗流程分析

    目录 前言 onBackPressed() onBackPressedDispatcher 前言 此文章主要解决拦截用户点击手机底部导航栏中的返回键时该事件的拦截: 此方法依然可以适用于fragment onBackPressed() 这是 activity 中自带的拦截返回的方法: 每当我们按下底部导航的返回键时,就会调用该事件,我们可以通过重写它来阻止 activity 的销毁 譬如下方代码,我们直接把 super 注释掉,那么点击返回键时就不会有任何反应,因为我们并没有针对性的进行响应的事

  • Android适配底部虚拟按键的方法详解

    最近项目进行适配的时候发现部分(如华为手机)存在底部虚拟按键的手机会因为虚拟按键的存在导致挡住部分界面,因为需要全屏显示,故调用虚拟按键隐藏方法使之隐藏,然而发现出现如下问题: 手动操作隐藏虚拟按键后出现长白条区域 不自动隐藏 滑出状态栏后虚拟按键也出来,状态栏隐藏后虚拟却不跟着隐藏 在没有虚拟按键的设备上影响了SurfaceView全屏显示图传(原本全屏显示的图传在切出去再进来时变成了小屏显示) 通过google了很多方法并尝试终于解决了这个问题,达到如下效果: 每次进入界面时虚拟按键自动隐藏

  • Android中双击返回键退出应用实例代码

    Android中双击返回键退出程序 1.在MyAppliction中(继承Application) //运用list来保存们每一个activity是关键 private List<Activity> mList = new LinkedList<Activity>(); //为了实现每次使用该类时不创建新的对象而创建的静态对象 private static MyApplication instance; //构造方法 public MyApplication() { } //实例化

  • 快速解决layui弹窗按enter键不停弹窗的问题

    问题描述:layui弹窗后按enter键不停的弹出,背景变得越来深 解决办法一:如图 解决办法二:(一个姓杨的大腿解决) 以上这篇快速解决layui弹窗按enter键不停弹窗的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • 快速解决android webview https图片不显示的问题

    Android webview 从Lollipop(5.0)开始webview默认不允许混合模式,https当中不能加载http资源,需要设置开启. 解决方法: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { webview.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); } 以上这篇快速解决android webview

  • 解决Android Studio 格式化快捷键和QQ 锁键盘快捷键冲突问题

    今天,简单讲讲android studio格式化的快捷键和qq快捷键之间的冲突的处理. 每次,当我打开QQ使用android studio格式化的快捷键Ctrl + Alt +L时,总是出现QQ 锁键盘的提示,这个冲突之前我是把QQ关掉,然后再格式化代码.可是这样就无法收到QQ的消息,所以在网上查找了资料,终于解决了问题.这里记录一下. 解决办法:去掉QQ里面 锁键盘快捷键 (1) 在QQ底部 点击 系统设置 (2) 选择 热键 -> 点 设置热键 (3) 在热键 里面 看到 锁定QQ Ctrl

  • 解决Android 沉浸式状态栏和华为虚拟按键冲突问题

    对于现在的 App 来说,布局页面基本都会用到沉浸式状态栏,单纯的沉浸式状态栏很容易解决,但是在华为手机上存在一个底部虚拟按键的问题,会导致页面底部和顶部出现很大的问题,比如页面底部导航栏被按键覆盖,导致底部无法操作,顶部状态栏布局被撑的很高,丑的不忍直视,这里就将两者的冲突问题一并解决!先看下实现的效果图: 这是我自己的手机,OnePlus 3T 7.1.1版本(免费广告,没给我钱的啊),不是华为的手机,但是有个虚拟按键可以设置,可以看到底部导航栏没有问题,顶部状态栏也成功实现,效果图看完,下

  • Android 应用按返回键退向后台运行实例代码

    Android应用开发按下返回键退向后台运行 我们日常使用的很多Android应用(如QQ.微信.微博),在应用的主界面按下返回键,应用并没有退出,而是进入后台运行. 那么,开发中是如何实现的呢?我找到了两种方法: 一.监测返回键 1.在Activity中重写onBackPressed()方法. @Override public void onBackPressed() { //此处写退向后台的处理 } 2.重写onKeyDown()方法(有的应用提示再次点击返回键退出应用就是在这里做的文章).

  • 快速解决Android平台移植ffmpeg的一些问题

    IT行业是一个踩在巨人肩膀上前进的行业,否则做的事情不一定有意义,所以我也是基于havlenapetr移植的ffmpeg基础上做了些改进,他做的主要贡献有: 1. 移植了ffmpeg并将与媒体相关的结构体在java层重新进行了封装,方便应用程序在java层直接操作ffmpeg API,如各种媒体格式转码及播放,如图1所示 2. 模仿Android的MediaPlayer类实现了ffmpeg的播放接口,如setDataSource(),setDisplay(),start(), stop(),pa

随机推荐