最近的项目要实现一个评论框,点击某处触发弹出软键盘,在软键盘上面显示EditText输入评论内容,还有2点需求
- 点击空白处关闭输入框并收起软键盘。
- 发送完评论后也关闭输入框并收起软键盘。
在使用DialogFragment中创建Dialog实现了评论框后,2可以正常实现,但是1存在输入框关闭了但是软键盘没有收起的情况。开始以为问题在android.view.inputmethod.InputMethodManager#hideSoftInputFromWindow(android.os.IBinder, int)
的调用传参上面,按照网上的方法,各种修改传入的windowToken和flag均无效。后续也在android.support.v4.app.DialogFragment#dismiss
、android.support.v4.app.DialogFragment#onDismiss
、android.app.Dialog#setOnDismissListener
中调用hideSoftInputFromWindow()均无效,没有办法只有断点跟进代码执行流程一探究竟。
android.view.inputmethod.InputMethodManager#hideSoftInputFromWindow(android.os.IBinder, int)
最终会调用它的重载方法android.view.inputmethod.InputMethodManager#hideSoftInputFromWindow(android.os.IBinder, int, android.os.ResultReceiver)
public boolean hideSoftInputFromWindow(IBinder windowToken, int flags,
ResultReceiver resultReceiver) {
checkFocus();
synchronized (mH) {
//我的主动调用运行到这里的时候,mServedView为null,所以并没有调用到后续的Binder通信代码。键盘自然不会收起了
if (mServedView == null || mServedView.getWindowToken() != windowToken) {
return false;
}
try {
return mService.hideSoftInput(mClient, flags, resultReceiver);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
在正常情况下mServedView是不为null的,那么mServedView是在哪里被赋值为null呢?是在这里:
/**
* Disconnect any existing input connection, clearing the served view.
*/
void finishInputLocked() {
mNextServedView = null;
if (mServedView != null) {
if (DEBUG) Log.v(TAG, "FINISH INPUT: mServedView=" + dumpViewInfo(mServedView));
if (mCurrentTextBoxAttribute != null) {
try {
mService.finishInput(mClient);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
mServedView = null; //看这里
mCompletions = null;
mServedConnecting = false;
clearConnectionLocked();
}
}
在这里定下断点,看看是怎么调用过来的呢?
这里看到了熟悉的android.app.Dialog#dismiss
那么就是说在当前情况下,在dialog dismiss的时候mServedView就被置为null,但是这个时候上面的一些列监听方法都还没用被调用,解决方法呢就是在mServedView被置空前调用hideSoftInputFromWindow(),至此问题解决。
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = object :Dialog(activity!!, setStyle()){
override fun dismiss() {
//关闭时机
KeyboardUtils.hideSoftInput(activity!!,inputDlg!!)
super.dismiss()
}
}
这个问题不难,但是还是稍微花了一点时间,意义就是遇到问题不一定要先多方搜索,可能自己花一点点时间看看内部,解决起来可能更快些。记录自勉,备查。