项目中需要对软键盘进行监听,控制它的显隐以及解决弹出时遮挡部分布局,本例子是在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);
本博客是参考网上有关知识并总结下来的,希望对你有帮助!