欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android开发之监听软键盘状态(弹出收回)

程序员文章站 2022-05-28 22:14:29
...

版权申明】非商业目的注明出处可*转载
博文地址:https://blog.csdn.net/ShuSheng0007/article/details/81511764
出自:shusheng007

概述

在我们开发过程中,有时需要监听手机软键盘状态,但是Android没有这样的API,所以需要我们自己处理。

实现方案

实现效果与原理

先上一张效果图
Android开发之监听软键盘状态(弹出收回)
可以看到我们准确的监听到了软键盘的弹出与收起事件

首先我们应该思考,从键盘弹出与隐藏这个动作中我们可以获得什么有用的信息呢?我们的View布局在此过程中有可能发生变化,如果我们可以监听到这个变化,而且判定是由于软键盘造成的就OK了。

具体代码

下面就是按照上面的思路写出的代码,具体分析在代码后面:

public class KeyboardStateObserver {

    private static final String TAG = KeyboardStateObserver.class.getSimpleName();

    public static KeyboardStateObserver getKeyboardStateObserver(Activity activity) {
        return new KeyboardStateObserver(activity);
    }

    private View mChildOfContent;
    private int usableHeightPrevious;
    private OnKeyboardVisibilityListener listener;

    public void setKeyboardVisibilityListener(OnKeyboardVisibilityListener listener) {
        this.listener = listener;
    }

    private KeyboardStateObserver(Activity activity) {
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
        mChildOfContent = content.getChildAt(0);
        mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            public void onGlobalLayout() {
                possiblyResizeChildOfContent();
            }
        });
    }

    private void possiblyResizeChildOfContent() {
        int usableHeightNow = computeUsableHeight();
        if (usableHeightNow != usableHeightPrevious) {
            int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;
            if (heightDifference > (usableHeightSansKeyboard / 4)) {
                if (listener != null) {
                    listener.onKeyboardShow();
                }
            } else {
                if (listener != null) {
                    listener.onKeyboardHide();
                }
            }
            usableHeightPrevious = usableHeightNow;
            Log.d(TAG,"usableHeightNow: " + usableHeightNow + " | usableHeightSansKeyboard:" + usableHeightSansKeyboard + " | heightDifference:" + heightDifference);
        }
    }

    private int computeUsableHeight() {
        Rect r = new Rect();
        mChildOfContent.getWindowVisibleDisplayFrame(r);

        Log.d(TAG,"rec bottom>" + r.bottom + " | rec top>" + r.top);
        return (r.bottom - r.top);// 全屏模式下: return r.bottom
    }

    public interface OnKeyboardVisibilityListener {
        void onKeyboardShow();

        void onKeyboardHide();
    }
}

上面的代码主要干了这几件事情:
1:我们获取到了设置到Activity 页面里面的View布局mChildOfContent ,这个就是我们在Layout文件中定义的View
2:通过mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener为其设置一个布局变化监听,只要布局有任何变化,都会触发这个监听。例如显示或隐藏某个view,由于输入使某个editview高度变化等。
3:计算布局变化的高度,如果变化的高度大于布局有效高度的1/4,我们认为这个布局变化是由软键盘造成的。
4:触发键盘显示与隐藏的监听。

如何使用

使用非常简单,获取实例,设置监听,在回调中处理逻辑即可。

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

     KeyboardStateObserver.getKeyboardStateObserver(this).
             setKeyboardVisibilityListener(new KeyboardStateObserver.OnKeyboardVisibilityListener() {
         @Override
         public void onKeyboardShow() {
             Toast.makeText(MainActivity.this,"键盘弹出",Toast.LENGTH_SHORT).show();
         }

         @Override
         public void onKeyboardHide() {
             Toast.makeText(MainActivity.this,"键盘收回",Toast.LENGTH_SHORT).show();
         }
     });
 }

note:此方式必须在弹出键盘时候,使页面原有布局发生变动,所以如果不起作用的话可以试着在AndroidManifest.xml文件中设置android:windowSoftInputMode=”adjustResize|stateHidden“”

隐患

由于我们设置为布局变动大于有效高度1/4就认为是由软键盘引起的,当遇到键盘高度小于1/4,或者布局由于设计原因会有高度变化大于1/4时都会出问题,但是这些情况都是极其罕见的。