从原理上分析解决软键盘的遮挡与隐藏问题, EditText 在 Toolbar 中键盘弹出问题

软键盘弹出遮挡界面的问题,在Actionbar出来之前,ScrollView已经能适应软键盘弹出自动变换大小,在弹出后可以滑动来改变位置从而不影响界面被软键盘遮挡.
但是如果在Toolbar中使用EditText,软键盘弹出时不影响Toolbar的显示而Toolbar下面的界面正常滑动, ScrollView就不能自适应了,还有如果不使用ScrollView,比如界面中是ListView或RecyclerView呢(外面不建议嵌套ScrollView),这时候又该如何控制?

更多文章请关注:blog.csdn.net/u012216274

一:从根目录解决软键盘弹出时的遮挡问题

1:先看效果图喽

键盘没有弹起时的状态
《从原理上分析解决软键盘的遮挡与隐藏问题, EditText 在 Toolbar 中键盘弹出问题》

键盘弹起后recyclerview仍可以滑动,滑动到底部后并不被软键盘遮住,并且toolbar不变
《从原理上分析解决软键盘的遮挡与隐藏问题, EditText 在 Toolbar 中键盘弹出问题》

2: 监听软键盘弹出与收回并修改界面布局大小

Android:windowSoftInputMode可以设置
《从原理上分析解决软键盘的遮挡与隐藏问题, EditText 在 Toolbar 中键盘弹出问题》

state开头只是显示的方式,而adjust才是影响到窗口的显示
adjustPan:会优先显示焦点内容区域,当获取焦点的区域所在位置会被软键盘覆盖时,点击内容会被整体往上弹起而防止被覆盖, 这种情况在Toolbar显示的时候,显然行不通
adjustResize:会留出软键盘的位置,将窗口的大小调整,相当RelativeLayout中的layout_above=”@id/软键盘”,
可以选择adjustResize方式来避免布局被往上弹起,同时需要监听窗口顶级视图的变化,再修改界面布局的大小

直接上代码,

private View ll_root;
/** * 窗体控件上一次的高度,用于监听键盘弹起 */
private int mLastHeight;


//onCreate中执行
final View decorView = this.getWindow().getDecorView();//获取window的视图
decorView.getViewTreeObserver().addOnGlobalLayoutListener(
        new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                Rect r = new Rect();
                decorView.getWindowVisibleDisplayFrame(r);
                //window视图添加控件此方法可能会被多次调用,防止重复调用
                if (mLastHeight != r.bottom) {
                    mLastHeight = r.bottom;
                    ViewGroup.LayoutParams params = ll_root.getLayoutParams();
                    params.height = r.bottom - ll_root.getTop();
                    ll_root.setLayoutParams(params);
                }
            }
        });

再看activity布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:id="@+id/ll_root" //这是要用到根目录 android:layout_width="match_parent" android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar  android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="48dp" android:minHeight="48dp" app:titleMarginStart="0dp" app:contentInsetStart="0dp" app:contentInsetRight="0dp" android:background="?attr/colorPrimary" />

    <android.support.v7.widget.RecyclerView  android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="match_parent"/>

</LinearLayout>


代码中ll_root即为activity中的根目录控件,可以为任何控件,摆脱了传统只能用scrollview的限制

二:软键盘的关闭

关闭软键盘没那么多坑,理解了它的原理就没有关不掉的软键盘啦,应用程序能通过调用 hideSoftInputFromWindow(IBinder windowToken, int flags) 方法请求InputMethodManager隐藏软键盘,但是必须提供一个窗口令牌作为参数,如果令牌不匹配当前接受输入的窗口令牌,InputMethodManager会拒绝请求,这确保恶意程序无法强制关闭由其他程序打开的软键盘.

(所以在activity上弹dialog或popupwindow, 关闭dialog或popupwindow的时候用第一种方式就会出现关不掉软键盘的情况)因为软键盘弹出所绑定的窗口跟activity窗口都不一样

第一种方式

/** * 关闭软键盘 */
public static void hideSoftInput(Activity context) {
    View view = context.getCurrentFocus();
    if (view != null) {
        InputMethodManager imm = (InputMethodManager) context
                .getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm.isActive()) {
            imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
    }
}

第二种方式

/** * 适合dialog, popupwindow弹窗时的软键盘关闭 * @params et 附着在dialog或popupwindow上的控件 */
public static void hideSoftInput(View et) {
    if (et == null) return;
    InputMethodManager imm = (InputMethodManager) et.getContext()
            .getSystemService(Context.INPUT_METHOD_SERVICE);
    if (imm.isActive()) {
        imm.hideSoftInputFromWindow(et.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

第一种方式只是适应activity中的弹窗,通过context.getCurrentFocus()找到窗口令牌, 但是在Dialog, PopupWindow上可能就行不通了,此时可以用第二种方式关闭, 传入的view为附着在dialog,popupwindow窗体上的view即可, 就是这么简单

最后附上源码download.csdn.net/detail/u012…

更多文章请关注:blog.csdn.net/u012216274

    原文作者:Android
    原文地址: https://juejin.im/entry/58f8a8efda2f60005da90844
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞