Close soft keyboard after RecyclerView view is updated with SearchView in Toolbar open?

Viewed 303

8/6/21 Added additional code updates below that also have been unsuccessful. Amazing, so many potential solutions that previous stackoverflow members have tried and none work for my use case...beyond Android frustrated.

I am trying to add code to close the soft keyboard after these user events:

  • A SearchView in my Toolbar returns a filtered list of CardViews that meet the user's search text criteria, from the full set of CardViews in the RecyclerView List.

  • User initiates a left-swipe to delete one of the filtered CardViews from the filtered list.

  • User confirms the Cardview delete by clicking "Ok" with a DialogFragment dialog.

  • The view updates as expected and returns the remaining filtered CardViews

  • The Toolbar is correctly showing the SearchView still open with the search text still showing on the mSearchView's EditText line

But the softkeyboard is popping open when the filtered list view is updated. So how do I keep the softkeyboard from popping open when the view updates?

Code I tried in the MainActivity that did not work:

1)
// this keeps the soft keyboard from opening but it closes the 
// SearchView in the Toolbar and I'd like to keep it open for the user
// with the user's 
if (mSearchView != null) {         
    mSearchView.clearFocus();  
}

2)
// Check if no view has focus:
View view = this.getCurrentFocus();
if (view != null) {  
    InputMethodManager imm = 
    (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}

8/6/21 Update:

None of these worked in the removeItem(), with "View viewRemove = MainActivity.this.getCurrentFocus();"

mSearchEditText.onEditorAction(EditorInfo.IME_ACTION_GO);
immMain.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY,0);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
immMain.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), inputMethodManager.HIDE_NOT_ALWAYS);
immMain.hideSoftInputFromWindow(viewRemove.getWindowToken(),0);             
immMain.hideSoftInputFromWindow(mSearchView.getWindowToken(),0);             
immMain.hideSoftInputFromWindow(mSearchEditText.getWindowToken(),0);
immMain.hideSoftInputFromWindow(viewRemove.getApplicationWindowToken(),0);
immMain.hideSoftInputFromWindow(mSearchView.getApplicationWindowToken(),0);
immMain.hideSoftInputFromWindow(mSearchEditText.getApplicationWindowToken(),0);       

Code I tried in the DialgoFragment that did not work:

1)
InputMethodManager imm =
    (InputMethodManager) rootView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm.isActive()) {
    imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
}

2)
View view = getActivity().getCurrentFocus();
if (view == null) view = new View(activity); {
    InputMethodManager imm = (InputMethodManager) 
        getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);    
    if (imm == null) { 
        return; 
    }
    else {
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
    }
}
 
3)
View view = getActivity().getCurrentFocus();
if (view == null) view = new View(activity); {
    InputMethodManager imm = (InputMethodManager) 
        getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
    if (imm == null) {
        return; }
    else {
        imm.hideSoftInputFromWindow(view.getWindowToken(),InputMethodManager.HIDE_NOT_ALWAYS);
    }

8/6/21 Update:

These also did not work in the Fragement:

((MainActivity) getActivity()).getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Objects.requireNonNull(this.getDialog().getWindow()).setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);

What am I missing here?


MainActivity

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.mainactiv_menu, menu);
    searchItem = menu.findItem(R.id.action_search);
    menu.findItem(R.id.action_search).setVisible(false);

    SearchManager searchManager = (SearchManager) MainActivity.this.getSystemService(Context.SEARCH_SERVICE);
    if (searchItem != null) {
        mSearchView = (SearchView) searchItem.getActionView();

        // Sets up a new a new SearchViewFocusListener so it can capture
        // a Back Button press by the member.
        mSearchView.setOnQueryTextFocusChangeListener(new SearchViewFocusListener(searchItem));
        // Associate the SearchView with the searchable configuration using
        // setSearchableInfo(getSearchableInfo).
        if (mSearchView != null) {
            mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
            EditText mSearchEditText = mSearchView.findViewById(androidx.appcompat.R.id.search_src_text);                mSearchEditText.setInputType(android.text.InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);

    
        // use the link to EditText of the SearchView so that a
        // TextWatcher can be used.
        mSearchEditText.addTextChangedListener(new TextWatcher() {
        
        @Override
        public void afterTextChanged(Editable s) {
            ... // search criteria code
            if (!mSearchView.isIconified() && searchList.size() > 0) {
                cardsAdapter.setFilter(searchList, s.toString());
                if (immMain != null) { 
                    immMain.hideSoftInputFromWindow(mSearchView.getWindowToken(),0);
                }
  return super.onCreateOptionsMenu(menu);
}     
               
DeleteCardViewFragment

public class DeleteCardViewFragment extends DialogFragment {

    public DeleteCardViewFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

        if (getActivity() != null) {
            Button btnOK = rootView.findViewById(R.id.btnOK);
            btnOK.setOnClickListener(v -> {
               ((MainActivity) getActivity()).removeItem(card);
            }
            // close soft keyboard from the Fragment code was unsuccessfully tried here
        }
        dismiss(); 

   MainActivity removeItem code:

   public void removeItem(@NonNull final Card card) {
       // code to remove the CardView from the RecyclerView list
       mRecyclerView.scrollToPosition(0);
       // MainActivity code was unsuccessfully added here to try to close the soft keyboard
   }
   // please note that a regular left-swipe by the user on a CardView, 
   // without an active SearchView open works as expected;  that is, the 
   // CardView is deleted and the user is returned to the updated 
   // CardView list and the soft keyboard does not open.  So the 
   // SearchView is probably causing the problem and something to do 
   // with the focus after the view is updated.



   
2 Answers

Try this code for keyboard close in fragment:

   /*--for hiding keyboard on click--*/
        InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
        //Find the currently focused view, so we can grab the correct window token from it.
        View view = getActivity().getCurrentFocus();
        //If no view currently has focus, create a new one, just so we can grab a window token from it
        if (view == null) {
            view = new View(getActivity());
        }
        assert imm != null;
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);

This code for keyboard close in Activity:

 /*--for hiding keyboard on click--*/
        InputMethodManager imm=(InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
        //Find the currently focused view, so we can grab the correct window token from it.
        View view = getCurrentFocus();
        //If no view currently has focus, create a new one, just so we can grab a window token from it
        if (view == null){
            view = new View(this);
        }
        assert imm != null;
        imm.hideSoftInputFromWindow(view.getWindowToken(), 0);

Add this code in manifest for MainActivity

android:windowSoftInputMode="stateAlwaysHidden

Some solutions you could try

  • Set windowSoftInputMode with stateHidden

<activity android:name=".MainActivity" android:windowSoftInputMode="stateHidden">

  • Add those attributes into parent view

android:focusable="true" android:focusableInTouchMode="true"

Related