简体   繁体   中英

How to make SearchView lose focus and collapse when clicking elsewhere on activity

In my app, I'm making a search interface in which the SearchView collapses and expands when it loses and gains focus respectively. However, the losing focus thing is only happening in two cases:

  1. When the back button is pressed.

  2. When the home icon beside the SearchView is pressed.

I want it to lose focus (and hence collapse) if the user clicks not only on these two things, but anywhere else on the screen (eg, any button or any blank portion of the screen without a view on it).

Well I found out the following solution. I used setOnTouchListener on every view that is not an instance of searchview to collapse the searchview. It worked perfect for me. Following is the code.

public void setupUI(View view) {

    if(!(view instanceof SearchView)) {

        view.setOnTouchListener(new OnTouchListener() {

            public boolean onTouch(View v, MotionEvent event) {
                searchMenuItem.collapseActionView();
                return false;
            }

        });
    }

    //If a layout container, iterate over children and seed recursion.
    if (view instanceof ViewGroup) {

        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {

            View innerView = ((ViewGroup) view).getChildAt(i);

            setupUI(innerView);
        }
    }
}

This is the answer I referred to.

Well, I have another simpler and tidier way of doing this. If you're using search widget as an action view in the toolbar ( https://developer.android.com/guide/topics/search/search-dialog#UsingSearchWidget ), you might want to make the SearchView lose focus and hide the keyboard when user touches anywhere else on the screen.

Instead of iterating and setting up touch listeners on every view in the hierarchy except the SearhView, you can simply make use of this solution since the SearchView has a AutoCompleteTextView in it.

Step 1: Make the parent view(content view of your activity) clickable and focusable by adding the following attribute

android:clickable="true"   
android:focusableInTouchMode="true"

Step 2: Set OnFocusChangeListener on the SearchView AutoCompleteTextView

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);

    final MenuItem search = menu.findItem(R.id.action_search);
    SearchView searchView = (SearchView) search.getActionView();

    // get a reference of the AutoCompleteTextView from the searchView
    AutoCompleteTextView searchSrcText = searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
    searchSrcText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (!hasFocus) {
                InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
                inputMethodManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
            }
        }
    });
    return super.onCreateOptionsMenu(menu);
}

That's it! Hopefully this is useful for future readers :)

in my case, i had to stop the search and close the keyboard, whenever user clicks on any other view, this worked for me.

    public static void hideSoftKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}


@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        View view = getCurrentFocus();

        if (view != null && view instanceof EditText) {
            Rect r = new Rect();
            view.getGlobalVisibleRect(r);
            int rawX = (int) ev.getRawX();
            int rawY = (int) ev.getRawY();
            if (!r.contains(rawX, rawY)) {
                hideSoftKeyboard(MainActivity.this);
            }
        }
    }
    return super.dispatchTouchEvent(ev);
}

This works for me, mOptionsMenu is saved in onCreateOptionsMenu:

public void setupUI(View view) {

    //Set up touch listener for non-text box views to hide keyboard.
    if(!(view instanceof EditText)) {

        view.setOnTouchListener(new View.OnTouchListener() {

            public boolean onTouch(View v, MotionEvent event) {
                hideSoftKeyboard(MainActivity.this);
                if(mOptionsMenu == null) return false;
                MenuItem searchMenuItem = mOptionsMenu.findItem(R.id.action_search);
                if(searchMenuItem == null) return false;
                ((SearchView)searchMenuItem.getActionView()).clearFocus();
                return false;
            }

        });
    }

    //If a layout container, iterate over children and seed recursion.
    if (view instanceof ViewGroup) {

        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {

            View innerView = ((ViewGroup) view).getChildAt(i);

            setupUI(innerView);
        }
    }
}

public static void hideSoftKeyboard(Activity activity) {
    InputMethodManager inputMethodManager = (InputMethodManager)  activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
    inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}

try this. It will make the searchView collapse when click anywhere on the screen.

searchView.isIconified = true

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM