热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

android开发键盘状态监听

1.背景相信大家在自己的项目中都会遇到EditText输入的问题,自然而然随之产生的就是让人头痛的键盘问题了,之所以说让人头疼是因为需求不同,设计不同,我们所要做的处理也不同,加上Googl

1.背景

相信大家在自己的项目中都会遇到EditText输入的问题,自然而然随之产生的就是让人头痛的键盘问题了,之所以说让人头疼是因为需求不同,设计不同,我们所要做的处理也不同,加上Google爸爸并没有针对键盘状态的API,所以只能靠我们自己处理。小白最近遇到的问题是:当键盘弹出的的时候,将输入框移到距离屏幕最上方20像素的地方,键盘收起时复位,所以有两个问题:

1.键盘弹出收起状态监听
2.将指定View移动到指定位置

来两张效果图:分别是弹出前和弹出后

这里写图片描述这里写图片描述

第二个问题好处理,我们可以使用以下几种方式将View移动到指定位置
1.位移动画
2. 属性动画
3.scrollTo/scrollBy
4.改变View的param

本文的目的就是针对第一个问题进行处理,最后以工具类的的形式贴出,然后以接口的形式暴露出键盘改变后的状态。方便大家使用。

2.windowSoftInputMode

首先针对键盘与窗口的交互模式,Android提供了一个属性windowSoftInputMode,该属性为我们的输入法创建了一个Dialog,并且将该Dialog的Window的某些参数(如Gravity)进行了设置,使之能够在底部或者全屏显示。当我们点击输入框时,系统对活动主窗口进行调整,从而为输入法腾出相应的空间,然后将该Dialog显示在底部,或者全屏显示。
该属性可选的值有两部分,一部分为软键盘的状态控制,另一部分是活动主窗口的调整。
windowSoftInputMode的取值可以是下面中的一个或者一个state和一个adjust组合的形式,使用|连接。

  1. stateUnspecified:软键盘的状态(隐藏还是可见)没有确定,系统会根据主题当中的设置选取一个合适的状态(默认值),设置改属性之后和未设置属性值效果图一样,省略
  2. stateUnchanged:软键盘被保持无论它上次是什么状态,是否可见或隐藏,当主窗口出现在前面时
  3. stateHidden:用户选择activity时,软键盘总是被隐藏,适用于界面初始化键盘收起状态(从别的页面启动该页面)
  4. stateAlwaysHidden:软键盘总是被隐藏的,当该 Activity主窗口获取焦点时(即使从别的页面返回到该页面)
  5. stateVisible :软键盘是可见的,当那个是正常合适的时 (当用户导航到 Activity主窗口,即使该窗口没有EditText )
  6. stateAlwaysVisible :当用户选择这个 Activity时,软键盘是可见的,和stateVisible不同的是,当我们跳转到下个界面,如果下个页面软键盘是隐藏的,而我们再次回来的时候,软键盘就会显示出来
  7. adjustUnspecified:设置软键盘与软件的显示内容之间的显示关系。默认的设置模式,在这中情况下,系统会根据界面选择不同的模式
  8. adjustResize:窗口总是调整屏幕的大小用以保证软键盘的显示空间,设置这个模式以后,窗口的decorView 大小本身并不会改变,但是我们的内容区 contentView (id = android.R.content) 会相应的缩小,为键盘的显示挪出空间。软键盘弹出后 contentView 高度变化的差值即为软键盘高度。
  9. adjustPan: 窗口(DecorView) 大小不变。当获取到焦点的 EditText 位于屏幕下方。这个属性用的比较多,常常配合 ScrollView 来使用
  10. adjustNothing:窗口不会做任何调整,contentView 大小也不会改变

3.键盘弹出收起监听的原理

上面我们介绍过的属性,有一个属性特别重要,那就是:adjustSize,设置adjustSzie属性后,所在Activity的DecorView的大小会发生变化 ,那我们是不是可以利用这个变化来监测键盘状态呢?当然可以:

  • 1.记录键盘未弹出时decorView 的高度,假设为:mOriginHeight,同时保存为变化之前的高度,假设为:mUnChangeHeight(这个可以监听ViewTreeObserver的OnGlobalLayoutListener接口-当一个视图树的布局发生改变时,可以被ViewTreeObserver监听)
  • 2.当键盘弹出后,整个页面的视图树会进行重绘,再次获取decoView的高度,假设为mCurrentHeight,同时更新mUnChangeHeight(始终更新为最后一次Decoview的高度)
  • 3.比较mOriginHeight和mCurrentHeight,若不相等则键盘状态发生变化,同时
  • 4.若发生变化,则比较mCurrentHeight和mOriginHeight,若相等,则键盘收起,若不相等,则键盘弹出,且键盘高度为:mOriginHeight - mCurrentHeight

4.封装实现

1.新建一个类,实现ViewTreeObserver.OnGlobalLayoutListener接口

public class KeyboardManager implementsViewTreeObserver.OnGlobalLayoutListener {
}

2.定义记录状态的变量

    private int mOriginHeight;//记录DecoView的原始高度
private int mPreHeight;//记录DecoView变化之前的高度

3.onGlobalLayout回调中判断键盘状态(键盘状态改变时,由于设置的adjustResize会触发该回调)

 @Override
public void onGlobalLayout() {
int currentHeight = mContentView.getHeight();//获取DecoView的高度
if (currentHeight == 0) {
return;
}
boolean isChange = false;//默认记录为未改变
if (mUnChangeHeight == 0) {
mUnChangeHeight = currentHeight;//DecoView的初始高度,页面的ViewTree第一次绘制完成时,会执行
mOriginHeight = currentHeight;
} else {
if (mUnChangeHeight != currentHeight) {//判断当前的高度是否和上一次的高度相等
isChange = true;
mUnChangeHeight = currentHeight;//更新保存DecoView最后一次的高度
} else {
isChange = false;
}
}
if (isChange) {
boolean isShow;
int keyboardHeight = 0;
if (mOriginHeight == currentHeight) {
isShow = false;
} else {
keyboardHeight = mOriginHeight - currentHeight;
isShow = true;
}
//根据isShow执行自己的操作
}
}

5工具类和使用

/**
* 键盘管理类
* Created by fanxudong on 2017/7/11.
*/


public class KeyboardManager implements ViewTreeObserver.OnGlobalLayoutListener {

private View mContentView;
private int mOriginHeight;
private int mUnChangeHeight;
private KeyBoardChangeListener mKeyBoardListen;

public static KeyboardManager getInstance(Activity activity){
return new KeyboardManager(activity);
}

public interface KeyBoardChangeListener {

void onKeyboardChange(boolean isShow, int keyboardHeight);

}

public void addOnKeyBoardChangeListener(KeyBoardChangeListener keyBoardChangeListen) {
this.mKeyBoardListen = keyBoardChangeListen;
}

public KeyboardManager(Activity activity) {
if (activity == null) {
return;
}
mCOntentView= findContentView(activity);
if (mContentView != null) {
addContentTreeObserver();
}
}

private View findContentView(Activity contextObj) {
return contextObj.findViewById(android.R.id.content);
}

private void addContentTreeObserver() {
mContentView.getViewTreeObserver().addOnGlobalLayoutListener(this);
}

@Override
public void onGlobalLayout() {
int currentHeight = mContentView.getHeight();
if (currentHeight == 0) {
return;
}
boolean isChange = false;
if (mUnChangeHeight == 0) {
mUnChangeHeight = currentHeight;
mOriginHeight = currentHeight;
} else {
if (mUnChangeHeight != currentHeight) {
isChange = true;
mUnChangeHeight = currentHeight;
} else {
isChange = false;
}
}
if (isChange) {
boolean isShow;
int keyboardHeight = 0;
if (mOriginHeight == currentHeight) {
isShow = false;
} else {
keyboardHeight = mOriginHeight - currentHeight;
isShow = true;
}

if (mKeyBoardListen != null) {
mKeyBoardListen.onKeyboardChange(isShow, keyboardHeight);
}
}
}

public void destroy() {
if (mContentView != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
mContentView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
}

}

使用:

 KeyboardManager.getInstance(this).addOnKeyBoardChangeListener(new KeyboardManager.KeyBoardChangeListener() {
@Override
public void onKeyboardChange(boolean isShow, int keyboardHeight) {
if(isShow){
//弹出
}else {
//收起
}
}
});

以上就是小白对键盘状态的总结,希望对大家有用!


推荐阅读
author-avatar
我们要疯_475
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有