Frage

I have an Activity with single Fragment on it. There is one EditText on the fragment.

The keyboard is popping up as soon the fragment is shown, however I managed to block it setting in the manifest android:windowSoftInputMode="stateHidden"

However, there also is a button, which opens a dialog with another EditText.

I have a method that automatically closes the keyboard on dialog dismiss.

public static void closeInput(final View caller) {      
    caller.post(new Runnable() {
        @Override
        public void run() {
            InputMethodManager imm = (InputMethodManager) caller.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(caller.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
        }
    });
}

The method is not a pretty hack and there is something wrong about it. Dialog's EditText has inputType="numberDecimal". The closeInput() seems to be not closing the keyboard, only changing it to the default alphabetical state.

What is going on here?

War es hilfreich?

Lösung

In my case I used method:

public static void closeInput(final View caller) {  
    caller.postDelayed(new Runnable() {
        @Override
        public void run() {
            InputMethodManager imm = (InputMethodManager) caller.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(caller.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }, 100);
}

It was refusing to work properly because of activity settings in Manifest, if I recall you can't have android:windowSoftInputMode="any_of_these" set

Andere Tipps

From fragments onCreateView() method you can do this:

getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN)

It will automatically hide soft keyboard on Dismiss of Dialog

in BaseDialog.java

protected void hideSoftKeyboard() {
    InputMethodManager imm = (InputMethodManager) this.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
    if (imm.isActive()) {
        imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
    }
}

In my case I was using:

android:windowSoftInputMode="adjustPan|stateVisible"

I deleted stateVisible:

android:windowSoftInputMode="adjustPan"

And onDismiss(), no need to call hideSoftInput method.

In my case, solution was to put keyboard hide in dialog dismiss

dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
        @Override
        public void onDismiss(DialogInterface dialog) {
            View view = activity.getCurrentFocus();
            if (view != null) {
                InputMethodManager inputManager = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
                inputManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
            }
        }
    }); 

Struggling with this issue and after reviewing the answers here, most seem to actually work. Since it was not desired to use a class rather just a builder, the answer https://stackoverflow.com/a/36422411/1815624 is not a workable solution.

Realizing others may have this same issue, an answer is being derived from both: https://stackoverflow.com/a/17393446/1815624 & https://stackoverflow.com/a/32648971/1815624

So the combination answer is grabbing the view from the fragment itself:

(Anyone got a reason not to?)

void closeKeyboard(final View caller){
    caller.post(new Runnable() {
        @Override
        public void run() {
            InputMethodManager imm = (InputMethodManager) caller.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(caller.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }
    });
}

...

dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
    @Override
    public void onDismiss(DialogInterface dialog) {
        closeKeyboard(getView());
    }
});

found a simple way to hide dialog keyboard

  1. dialog.setCanceledOnTouchOutside(false)
  2. call hideKeyboardFromDialogBeforeDismiss() before dialog dismiss, may be on cancel button clicked event, shouldn't call in onDismiss or onCancelListener
    binding.cancelBtn.setOnClickListener {       
        STSystemUtil.hideKeyboardFromDialogBeforeDismiss(dialog = dialog) 
        binding.root.postDelayed({ dialog?.dismiss() }, 200)
    }
    
    @JvmStatic
    @JvmOverloads
    fun getInputMethodManager(context: Context? = STInitializer.application()): InputMethodManager? {
        return context?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager?
    }

    /*
     * 注意: 如果 dialog 包含一个或者多个EditText, 点击外部(canceledOnTouchOutside==true)不会隐藏已经显示的输入法弹框, 且通过点击取消按钮必须先隐藏输入法弹框再延时 dismiss, 因为在 onCancel/onDismiss 中 dialog?.currentFocus?.windowToken 必然已经是 null, 且 inputMethodManager?.isActive 必然是 false
     * ----> canceledOnTouchOutside = false
     * ----> binding.cancelBtn.setOnClickListener {
     *          STSystemUtil.hideKeyboardFromDialogBeforeDismiss(dialog)
     *          binding.root.postDelayed({ dialog?.dismiss() }, 200)
     *       }
     */
    @JvmStatic
    @JvmOverloads
    fun hideKeyboardFromDialogBeforeDismiss(context: Context? = STInitializer.application(), dialog: Dialog? = null) {
        val inputMethodManager: InputMethodManager? = getInputMethodManager(context)
        if (dialog == null) {
            if (inputMethodManager?.isActive == true) {
                inputMethodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS)
            }
        } else {
            inputMethodManager?.hideSoftInputFromWindow(dialog.currentFocus?.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
        }
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top