软键盘弹出遮挡界面的问题,在Actionbar出来之前,ScrollView已经能适应软键盘弹出自动变换大小,在弹出后可以滑动来改变位置从而不影响界面被软键盘遮挡.
但是如果在Toolbar中使用EditText,软键盘弹出时不影响Toolbar的显示而Toolbar下面的界面正常滑动, ScrollView就不能自适应了,还有如果不使用ScrollView,比如界面中是ListView或RecyclerView呢(外面不建议嵌套ScrollView),这时候又该如何控制?
更多文章请关注: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即可, 就是这么简单
最后附上源码download.csdn.net/detail/u012…