Android监听软键盘的显示与隐藏

hah.png

前一阵项目开发遇到一个问题。需求是这样的,就是在开播的页面,默认进入展示了两排的标签。标签采用流式布局的形式。展示在直播标题输入框的下面。然后,当用户点击输入框输入文字的时候,这时,软键盘弹出,要求原本在输入框下面的标签布局消失,当用户输入完,返回键使软键盘消失后,标签布局要重新展示出来。刚开始听到这个需求的时候,没觉着有任何的技术难度。无非监听一下软键盘的显示与消失么。当监听到软键盘显示时,将标签布局置为gone;当监听到软键盘消失的时候,再将标签布局置为visible就OK的了。没错,思路完全正确。但是,怎么监听确确实实折腾了我一个下午。

在这里,要和广大朋友声明的一件比较操蛋的事就是,谷歌并没有提供这一类接口来进行软键盘显示与消失的监听。那么,是不是我们就没办法获取这一状态的改变呢?当然不是,我们可以监听根布局的布局高度变化来间接的对软键盘的显示与消失做出判断,并且还可以获取到软键盘的高度(注:当清单文件中windowSoftInputMode="adjustNothing"此方法不生效)。这里有一个知识点还望大家自行科普一下,本篇文章就不做描述了,那就是Android中和软键盘相关的Windowsoftinputmode属性。这里留下一个链接,希望可以帮助到大家。
Windowsoftinputmode属性使用

接下来,直接上代码,代码中我做好了注释,相信应该很容易理解:

public class KeyboardChangeListener implements ViewTreeObserver.OnGlobalLayoutListener {

    private static final String TAG = "ListenerHandler";
    private View mContentView;   // 当前界面的根视图
    private int mOriginHeight;   // 此时根视图的高度
    private int mPreHeight;   // 改变之前根视图的高度
    private KeyBoardListener mKeyBoardListen;

    public KeyboardChangeListener(Activity activity) {
        if (activity == null) {
            Log.i(TAG, "contextObj is null");
            return;
        }
        mContentView = findContentView(activity);
        if (mContentView != null) {
            addContentTreeObserver();
        }
    }

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

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

    @Override
    public void onGlobalLayout() {
        // 先获取到当前根视图的高度
        int currHeight = mContentView.getHeight();
        if (currHeight == 0) {
            return;
        }

        boolean hasChange = false;
        if (mPreHeight == 0) {
            mPreHeight = currHeight;
            mOriginHeight = currHeight;
        } else {
            if (mPreHeight != currHeight) {
                hasChange = true;
                mPreHeight = currHeight;
            } else {
                hasChange = false;
            }
        }
        if (hasChange) {
            boolean isShow;
            int keyboardHeight = 0;
            // 当当前的根视图高度和初始化时的高度一样时,说明此时软键盘没有显示,是消失状态
            if (mOriginHeight == currHeight) {
                //hidden
                isShow = false;
            } else {
                // 此时,根视图的高度减少了,而减少的部分就是软键盘的高度,软键盘显示状态
                //show
                keyboardHeight = mOriginHeight - currHeight;
                isShow = true;
            }

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

    public void setKeyBoardListener(KeyBoardListener keyBoardListen) {
        this.mKeyBoardListen = keyBoardListen;
    }

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

    public interface KeyBoardListener {

        void onKeyboardChange(boolean isShow, int keyboardHeight);
    }
}

以上便是实现软件盘显示和消失的监听,然后我们看一下具体的调用(布局中我设置了一个EditText,用于调起软键盘):

public class MainActivity extends AppCompatActivity implements KeyboardChangeListener.KeyBoardListener {
    private static final String TAG = "MainActivity";
    private KeyboardChangeListener mKeyboardChangeListener;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mKeyboardChangeListener = new KeyboardChangeListener(this);
        mKeyboardChangeListener.setKeyBoardListener(this);
    }

    @Override
    public void onKeyboardChange(boolean isShow, int keyboardHeight) {
        Log.d(TAG, "onKeyboardChange() called with: " + "isShow = [" + isShow + "], keyboardHeight = [" + keyboardHeight + "]");
    }
}

下面是我在logcat中的log截图,实现了对软键盘显示和消失的监听,并且获取到当前软键盘的高度:

log.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342