最近项目中需要有一个地方隐藏键盘和显示键盘。其实是一个比较简单的问题,但是由于我们项目架构的原因。一个Activity中内嵌了很多个Fragment,通过事件去驱动不同的Fragment展现出来。举个例子,注册流程实际上是一个Activity,然后其中包含了ResetPasswordFragment,forgetPasswordFramgent,loginFragment等等。如果用户在Login界面的EditView输入账号密码的时候,通过back键恢复到了上一个Activity的时候,键盘是无法隐藏掉的。

为了解决这个问题,我的第一次解决的方案是这样。通过在VM层中添加一个变量hideSoftKeyboard,然后给XML设定一个自定义的BindingAdapter,传入这个变量。

@BindingAdapter("showSoftKeyboard")
public static void showSoftKeyboard(View view, Boolean showSoftKeyboard) {
        if (!showSoftKeyboard) {
            InputMethodManager imm = (InputMethodManager) editText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }

但是这样会出现一个问题,即toggleSoftInput是一个二元的开关,第一次开,第二次关。很蛋疼。下来我去Google寻找答案。找到了一个比较靠谱的SOF。小哥先吐槽了一下Android的API设计,确实比较蛋疼,居然没有给一个相应的API来控制展示和隐藏。需要通过InputMethodManager来接管,但是还需要传入一个Context才能获得IMM,获得后还需要具体的View才可以设置键盘的隐藏。按理说,系统直接提供一个方法**Keyboard.hide()Keyboard.show()**不就挺好。在需要的时候就直接展现和隐藏就好。我在想这可能是因为,Android为了将这个控制权放到系统层面,这样可以避免恶意软件强制系统其他应用不会隐藏按键,导致用户体验崩裂。

既然这样,我就采用了另外的方法,做了一个Util类,来控制显示和隐藏。

public class KeyBoardUtil {
	private KeyBoardUtil() {}

	public static void hideSoftKeyboard(Activity activity) {
		View focusedView = activity.getCurrentFocus();
		if(focusedView != null) {
			 InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
			 imm.hideSoftInputFromWindow(focusedView.getWindowToken(), 0);
		}
	}

	public static void showSoftKeyboard(View view) {
		InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
		view.requestFocus();
		imm.showSoftInput(view, 0);
}

在需要展示和隐藏的地方直接调用去传递对应的参数即可。这个时候我们的BindingAdapter就可以改造成这样:

@BindingAdapter("showSoftKeyboard")
public static void showSoftKeyboard(View view, Boolean showSoftKeyboard) {
        if (showSoftKeyboard) {
            KeyBoardUtil.showSoftKeyBoard(view);
        } else {
	        Context context = view.getContext();
	        if (context instanceof Activity) {
		        Activity act = (Activity)context;
		        KeyBoardUtil.hideSoftKeyBoard(act);
		    }
        }
    }