AlertDialog & EditText & 软键盘

两个问题:

  • AlertDialog 中默认选中 EditText 焦点,并且弹出软键盘
  • AlertDialog 中 EditText 无法弹出软键盘

两个问题都在不同场景出现过;

对于第一个问题:
业务场景是使用绘制的键盘布局替代系统的软键盘,这时候需要阻止系统软键盘的弹出:EditText.setShowSoftInputOnFocus(false)
然而当 AlertDialog.show() 之后软键盘自动弹出,推测是 AlertDialog 加载时可能会根据子 View 去调用 InputMethodManager 导致的(误)。

之后就找到 AlertDialog 中的一段注释:

 * <p>The AlertDialog class takes care of automatically setting
 * {@link android.view.WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM
 * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM} for you based on whether
 * any views in the dialog return true from {@link View#onCheckIsTextEditor()
 * View.onCheckIsTextEditor()}.  Generally you want this set for a Dialog
 * without text editors, so that it will be placed on top of the current
 * input method UI.  You can modify this behavior by forcing the flag to your
 * desired mode after calling {@link #onCreate}

提到了 FLAG_ALT_FOCUSABLE_IM ,flag 让 AlertDialog 的子 View. onCheckIsTextEditor() return true 以此让弹窗在最近的输入框 UI 上面,但是这种情况是默认了弹窗中没有输入框;

然后 Dialog 中也标注:

 * <p>Often you will want to have a Dialog display on top of the current
 * input method, because there is no reason for it to accept text.  You can
 * do this by setting the {@link WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM
 * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM} window flag (assuming
 * your Dialog takes input focus, as it the default) with the following code:
 * 
 * <pre>
 * getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
 *         WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);</pre>

两段注释都表明 flag FLAG_ALT_FOCUSABLE_IM 决定了 Dialog 和 软键盘之间的交互。

所以回到开头提到的两个问题都可以通过设置 / 清除 FLAG 实现:

// 阻止软键盘自动弹出
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
// 解决 EditText 无法弹出软键盘
getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
           WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);