android开发键盘状态监听

来源:互联网 发布:cad软件下载 编辑:程序博客网 时间:2024/06/03 11:18

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 {                    //收起                }            }        });

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

原创粉丝点击