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

来源:互联网 发布:linux绑定域名命令 编辑:程序博客网 时间:2024/04/28 20:18

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

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


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

1:先看效果图喽

键盘没有弹起时的状态
这里写图片描述

键盘弹起后recyclerview仍可以滑动,滑动到底部后并不被软键盘遮住,并且toolbar不变
这里写图片描述

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

android:windowSoftInputMode可以设置
这里写图片描述

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即可, 就是这么简单

最后附上源码http://download.csdn.net/detail/u012216274/9820540

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

1 0