Android软键盘的监听,显隐控制以以及弹出遮挡布局的解决方法(用于fragment,dialog)

项目中需要对软键盘进行监听,控制它的显隐以及解决弹出时遮挡部分布局,本例子是在fragment和dialog使用,activity中未测试,不过从代码上看是可以使用的。

包含对软键盘进行监听,控制它的显隐以及解决弹出时遮挡部分布局的工具类如下:

public class SoftKeyBoardListener {

    public static boolean softKeyFlag;//软键盘显隐标记.true为显示


    public static void hideSoftKeyboard(Context context, View view) {
        InputMethodManager mInputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        if (mInputMethodManager != null) {
            mInputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
            softKeyFlag = false;
        }

    }

    public static void showSoftKeyboard(Context context, View view) {
        InputMethodManager mInputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        if (mInputMethodManager != null) {
            view.requestFocus();//要先设置焦点
           // view.setVisibility();//可以写控制view的显隐
            mInputMethodManager.showSoftInput(view, 0);
            softKeyFlag = true;
        }
    }

    /**
     * 软键盘弹出布局向上滑动
     *
     * @param rootView   根布局
     * @param bottomView 需要显示的最下方View,
     */
    public static void layoutSlideListener(final View rootView, final View bottomView) {
        rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect rect = new Rect();
                rootView.getWindowVisibleDisplayFrame(rect);//获取rootView的可视区域
                int invisibleHeight = rootView.getRootView().getHeight() - rect.bottom;//获取rootView的不可视区域高度
                if (invisibleHeight > 150) { //键盘显示
                    int[] location = new int[2];
                    bottomView.getLocationInWindow(location); //获取bottomView的坐标
                    int scrollHeight = (location[1] + bottomView.getHeight()) - rect.bottom + 40;//算出需要滚动的高度(与初始布局的偏移量,可调整)
                    if (scrollHeight != 0) {//防止界面元素改变调用监听,使界面上下跳动,如验证码倒计时
                        rootView.scrollTo(0, scrollHeight);
                    }
                } else {
                    rootView.scrollTo(0, 0);
                }
            }
        });
    }

}

1.Android中软键盘的管理主要是通过InputMethodManager类来完成的。
获取方法:(InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
1.1软键盘的隐藏使用的是 hideSoftInputFromWindow(IBinder windowToken, int flags)方法,第一个参数为:当前布局的windowToken;(activity,fragment,dialog获取的方式不一样,下文提到)第二个参数意义不大,设置为0;
例如:在dialog的点击事件中,点击其他控件时隐藏软键盘:

......
 switch (view.getId()) {
                    case R.id.bt_editor_name_confirm:
                      SoftKeyBoardListener.hideSoftKeyboard(context, view);
                        break;
                        ......
                        }
                        

1.2软键盘的显示使用的是showSoftInput(View view, int flags)方法,第一个参数必须是EditText,或者EditText的子类,其他控件不起作用;第二个参数意义不大,设置为0;
xml的EditText可不用设置android:focusable=“true” android:focusableInTouchMode="true"属性,因为代码中已经实现 view.requestFocus();这样更在灵活的控制。
使用如下:当点击EditText显示软键盘

private EditText mEditorNameAlterEt;
mEditorNameAlterEt = dialog.getWindow().findViewById(R.id.et_editor_name_alter);
.....
SoftKeyBoardListener.showSoftKeyboard(context, mEditorNameAlterEt);

注意:1.布局必须完全加载完成;2.view必须可见;3.view必须已获取焦点;否则showSoftInput方法不起作用;

2.判断当前页面是否有软键盘:之前网上有很多的例子比如:使用OnGlobalLayoutListener监听当前布局视图高度的变化等,我基本都用过,但是并不满足我的需求,因为OnGlobalLayoutListener需要布局发现改变才会调用,比如我打开dialog时,我需要监听是否有软键盘,有则点击dialog区域外时隐藏软键盘,无则关闭dialog;而且使用OnGlobalLayoutListener还会产生许多的页面bug;
解决方法:就是在工具类中设置个显隐的标记softKeyFlag,true为显示;第一次打开dialog,softKeyFlag初始值为false;

   //若有软键盘则隐藏,无则关闭dialog
                if (SoftKeyBoardListener.softKeyFlag) {
                    SoftKeyBoardListener.hideSoftKeyboard(getContext(), getCurrentFocus());
                } else {
                    dismiss();
                }

这里不能在xml中设置editText的焦点,即android:focusable="true"和android:focusableInTouchMode="true"属性,若设置了显示editText会自动弹出软键盘,但不会改变softKeyFlag的值。若想实现自动弹出软键盘,则在显示editText时调用工具类的showSoftKeyboard方法(自动为手动,效果还是一样)。

3.点击EditText以外隐藏软键盘,对dialog区域外进行监听:
项目需求:点击自定义dialog中的EditText弹出软键盘,点击非EditText区域隐藏软键盘,点击dialog以外区域先判断是否有软键盘,有则点击dialog区域外时隐藏软键盘,无则关闭dialog。
重写dialog的onTouchEvent方法:

 @Override
    public boolean onTouchEvent(@NonNull MotionEvent event) {
        if (getCurrentFocus() != null) {
            //点击EditText以外区域隐藏软键盘
            InputMethodManager mInputMethodManager = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            mInputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
        }
        //对dialog区域外进行监听,数值按照实际情况调整
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (!(event.getX() >= -10 && event.getY() >= -10)
             || event.getX() >= calendarLayout.getWidth() + 10    
             || event.getY() >= calendarLayout.getHeight() + 20) {
                //若有软键盘则关闭,无则关闭dialog
                if (SoftKeyBoardListener.softKeyFlag) {
                    SoftKeyBoardListener.hideSoftKeyboard(getContext(), getCurrentFocus());
                } else {
                    dismiss();
                }
            }
        }
        return super.onTouchEvent(event);
    }

注意WindowToken的获取方式:fragmnt,dialog,activity的获取方式都不一样!

fragment:hideSoftInputFromWindow(view.getWindowToken(),0);//view为监听的根布局,比如我监听dialog,就是diaog的xml
dialog:hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),0);
activity:hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(),0);

4.弹出软键盘遮挡部分页面的解决方法:
就是工具类中的layoutSlideListener方法,需要两个参数:一个是根布局,另一个是需要显示的最下方的控件,如果整体布局滑动的距离不是很满意,可以根据自己的情况调整scrollHeight 的值(+或者-)
dialog中使用:

View view = View.inflate(context, dialogLayout, null);
....
SoftKeyBoardListener.layoutSlideListener(view, mEditorNameFrameIv);

本博客是参考网上有关知识并总结下来的,希望对你有帮助!

你可能感兴趣的:(Android,软键盘,dialog)