Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 (e.g., any button or any blank portion of the screen without a view on it).

like image 733
Pankaj Singhal Avatar asked Jul 11 '13 10:07

Pankaj Singhal


3 Answers

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 :)

like image 145
Philemon Khor Avatar answered Nov 12 '22 07:11

Philemon Khor


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.

like image 10
Pankaj Singhal Avatar answered Nov 12 '22 06:11

Pankaj Singhal


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);
}
like image 1
Usama Saeed US Avatar answered Nov 12 '22 07:11

Usama Saeed US