如何获取Android软键盘状态和软键盘高度

2024-08-31 00:18

本文主要是介绍如何获取Android软键盘状态和软键盘高度,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

应用场景

在Android应用中有时会需要获取软键盘的状态(即软键盘是显示还是隐藏)和软键盘的高度。这里列举了一些可能的应用场景。

  1. 场景一
    当软键盘显示时,按下返回键应当是收起软键盘,而不是回退到上一个界面,但部分机型在返回键处理上有bug,按下返回键后,虽然软键盘会自动收起,但不会消费返回事件,导致Activity还会收到这次返回事件,执行回退操作,这时就需要判断,如果软键盘刚刚由显示变为隐藏状态,就不执行回退操作。
  2. 场景二
    当软键盘弹出后,会将界面底部到中间的一大部分全部挡住,如果用户要查看、操作被覆盖的区域,必须先收起软键盘,这会影响用户交互。所以通常需要在软键盘弹出后,将底部的一些View,例如Button,移到软键盘的上方,方便用户操作。

API的困境

Android SDK中没有提供任何API来直接获取软键盘的状态和软键盘的高度,网上很多资料说InputMethodManager的isActive()方法可以获取软键盘状态,不过实际测试发现,这个方法并没有什么用,如果它返回false,可以判断软键盘一定是隐藏的,但如果它返回true,软键盘既可能是显示的,也可能是隐藏的。所以并不能通过isActive()方法来判断软键盘究竟是显示还是隐藏的。要想获取软键盘的状态和软键盘的高度,只能通过间接方法实现。

注册布局变化监听

在Android中当软键盘由隐藏变为显示,或由显示变为隐藏时,会触发当前布局中View的全局布局变化。通过监听全局布局的变化就可以得知软键盘的状态。
Android框架提供了一个ViewTreeObserver类,它是一个View视图树的观察者类。ViewTreeObserver类中定义了一系列的公共接口(public interface)。当一个View attach到一个窗口上时就会创建一个ViewTreeObserver对象,这样当一个View的视图树发生改变时,就会调用该对象的某个方法,将事件通知给每个注册的监听者。
OnGlobalLayoutListener是ViewTreeObserver中定义的众多接口中的一个,它用来监听一个视图树中全局布局的改变或者视图树中的某个视图的可视状态的改变。当软键盘由隐藏变为显示,或由显示变为隐藏时,都会调用当前布局中所有存在的View中的ViewTreeObserver对象的dispatchOnGlobalLayout()方法,此方法中会遍历所有已注册的OnGlobalLayoutListener,执行相应的回调方法,将全局布局改变的消息通知给每个注册的监听者。
向一个View中的ViewTreeObserver注册OnGlobalLayoutListener的方法如下。

view.getViewTreeObserver().addOnGlobalLayoutListener(listener);
  • 1

注册OnGlobalLayoutListener时有一些需要注意的地方。

  1. 注册的监听在不使用时需要调用removeOnGlobalLayoutListener或removeGlobalOnLayoutListener来移除监听,不然可能会导致内存泄露。通常可以在Activity的onCreate()方法中注册监听,在onDestory()方法中移除监听。
  2. 并不是只有显示和隐藏软键盘会触发OnGlobalLayoutListener中的回调,一个View在绘制完成,或者消失时都会触发OnGlobalLayoutListener中的回调(由于在onCreate中无法获取一个View的宽度和高度,很多时候就是通过注册OnGlobalLayoutListener,在OnGlobalLayoutListener的回调中来获取一个View的宽度和高度)。

为了在OnGlobalLayoutListener的回调中准确的判断是否是由于软键盘状态改变引起的,以及获取软键盘的高度,还需要另外一个接口。

获取当前窗口可见的显示区域大小

在View中提供了一个方法getWindowVisibleDisplayFrame(),此方法会返回该view所附着的窗口的可见区域大小。当软键盘显示时,窗口的可见区域大小会被压缩,当软键盘隐藏时,窗口的可见区域大小会还原。不过并不是只有软键盘的显示和隐藏会影响窗口的可见区域大小,像大多数的平板和部分手机上有一排虚拟按键(虚拟的返回键,Home键等),虚拟按键的显示和隐藏也会引起窗口可见区域的变化。不过好在除了软键盘外,其他操作对窗口可见区域的影响占整个屏幕大小的比例都不是很大,通过设置一个合理的阈值,就可以较准确的判断出是否是软键盘显示和隐藏引起的布局变化。
此外,getWindowVisibleDisplayFrame()会返回窗口的可见区域高度,通过和屏幕高度相减,就可以得到软键盘的高度了。

监听软键盘的状态变化

在获取到软键盘的状态和高度后就可以执行需要的操作了。如重新布局按钮位置,设置变量,记录当前软键盘状态和上次软键盘隐藏时间等。不过如果有多个类需要根据软键盘状态来执行一些操作,如果每个类中都去这样做一遍就很麻烦,而且也没有必要。这时在可以自行定义一个接口,在主Activity中对软键盘状态变化进行监听,其他对软键盘状态感兴趣的类,向主Activity中注册软键盘状态变化监听。在主Activity中,当软键盘状态发生改变时通知监听者。

完整示例代码

完整的示例代码如下。

public interface OnSoftKeyboardStateChangedListener {public void OnSoftKeyboardStateChanged(boolean isKeyBoardShow, int keyboardHeight);
}//注册软键盘状态变化监听
public void addSoftKeyboardChangedListener(OnSoftKeyboardStateChangedListener listener) {if (listener != null) {mKeyboardStateListeners.add(listener);}
}
//取消软键盘状态变化监听
public void removeSoftKeyboardChangedListener(OnSoftKeyboardStateChangedListener listener) {if (listener != null) {mKeyboardStateListeners.remove(listener);}
}private ArrayList<OnSoftKeyboardStateChangedListener> mKeyboardStateListeners;      //软键盘状态监听列表
private OnGlobalLayoutListener mLayoutChangeListener;
private boolean mIsSoftKeyboardShowing;@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);mIsSoftKeyboardShowing = false;mKeyboardStateListeners = new ArrayList<OnSoftKeyboardStateChangedListener>();mLayoutChangeListener = new OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {//判断窗口可见区域大小Rect r = new Rect();getWindow().getDecorView().getWindowVisibleDisplayFrame(r);//如果屏幕高度和Window可见区域高度差值大于整个屏幕高度的1/3,则表示软键盘显示中,否则软键盘为隐藏状态。int heightDifference = screenHeight - (r.bottom - r.top);boolean isKeyboardShowing = heightDifference > screenHeight/3;//如果之前软键盘状态为显示,现在为关闭,或者之前为关闭,现在为显示,则表示软键盘的状态发生了改变if ((mIsSoftKeyboardShowing && !isKeyboardShowing) || (!mIsSoftKeyboardShowing && isKeyboardShowing)) {mIsSoftKeyboardShowing = isKeyboardShowing;for (int i = 0; i < mKeyboardStateListeners.size(); i++) {OnSoftKeyboardStateChangedListener listener = mKeyboardStateListeners.get(i);listener.OnSoftKeyboardStateChanged(mIsSoftKeyboardShowing, heightDifference);}}}};//注册布局变化监听getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(mLayoutChangeListener);
}@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
@Override
protected void onDestroy() {//移除布局变化监听if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {getWindow().getDecorView().getViewTreeObserver().removeOnGlobalLayoutListener(mLayoutChangeListener);} else {getWindow().getDecorView().getViewTreeObserver().removeGlobalOnLayoutListener(mLayoutChangeListener);}super.onDestroy();
};
  • 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

其中screenHeight 是屏幕高度,关于屏幕高度的获取方法,网上有很多,这里就不介绍了。

这篇关于如何获取Android软键盘状态和软键盘高度的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1122339

相关文章

SpringMVC高效获取JavaBean对象指南

《SpringMVC高效获取JavaBean对象指南》SpringMVC通过数据绑定自动将请求参数映射到JavaBean,支持表单、URL及JSON数据,需用@ModelAttribute、@Requ... 目录Spring MVC 获取 JavaBean 对象指南核心机制:数据绑定实现步骤1. 定义 Ja

C++中RAII资源获取即初始化

《C++中RAII资源获取即初始化》RAII通过构造/析构自动管理资源生命周期,确保安全释放,本文就来介绍一下C++中的RAII技术及其应用,具有一定的参考价值,感兴趣的可以了解一下... 目录一、核心原理与机制二、标准库中的RAII实现三、自定义RAII类设计原则四、常见应用场景1. 内存管理2. 文件操

SpringBoot服务获取Pod当前IP的两种方案

《SpringBoot服务获取Pod当前IP的两种方案》在Kubernetes集群中,SpringBoot服务获取Pod当前IP的方案主要有两种,通过环境变量注入或通过Java代码动态获取网络接口IP... 目录方案一:通过 Kubernetes Downward API 注入环境变量原理步骤方案二:通过

使用Python实现获取屏幕像素颜色值

《使用Python实现获取屏幕像素颜色值》这篇文章主要为大家详细介绍了如何使用Python实现获取屏幕像素颜色值,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 一、一个小工具,按住F10键,颜色值会跟着显示。完整代码import tkinter as tkimport pyau

python获取cmd环境变量值的实现代码

《python获取cmd环境变量值的实现代码》:本文主要介绍在Python中获取命令行(cmd)环境变量的值,可以使用标准库中的os模块,需要的朋友可以参考下... 前言全局说明在执行py过程中,总要使用到系统环境变量一、说明1.1 环境:Windows 11 家庭版 24H2 26100.4061

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

IIS 7.0 及更高版本中的 FTP 状态代码

《IIS7.0及更高版本中的FTP状态代码》本文介绍IIS7.0中的FTP状态代码,方便大家在使用iis中发现ftp的问题... 简介尝试使用 FTP 访问运行 Internet Information Services (IIS) 7.0 或更高版本的服务器上的内容时,IIS 将返回指示响应状态的数字代

使用Python获取JS加载的数据的多种实现方法

《使用Python获取JS加载的数据的多种实现方法》在当今的互联网时代,网页数据的动态加载已经成为一种常见的技术手段,许多现代网站通过JavaScript(JS)动态加载内容,这使得传统的静态网页爬取... 目录引言一、动态 网页与js加载数据的原理二、python爬取JS加载数据的方法(一)分析网络请求1

通过cmd获取网卡速率的代码

《通过cmd获取网卡速率的代码》今天从群里看到通过bat获取网卡速率两段代码,感觉还不错,学习bat的朋友可以参考一下... 1、本机有线网卡支持的最高速度:%v%@echo off & setlocal enabledelayedexpansionecho 代码开始echo 65001编码获取: >

使用Python实现调用API获取图片存储到本地的方法

《使用Python实现调用API获取图片存储到本地的方法》开发一个自动化工具,用于从JSON数据源中提取图像ID,通过调用指定API获取未经压缩的原始图像文件,并确保下载结果与Postman等工具直接... 目录使用python实现调用API获取图片存储到本地1、项目概述2、核心功能3、环境准备4、代码实现