SearchView's OnCloseListener doesn't work

AndroidAndroid 3.0-HoneycombAndroid 4.0-Ice-Cream-SandwichAndroid Actionbar

Android Problem Overview


I'm trying to add support for the SearchView in the Android 3.0+ ActionBar, but I can't get the OnCloseListener to work.

Here's my code:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
	getMenuInflater().inflate(R.menu.menu, menu);
	searchView = (SearchView) menu.findItem(R.id.search_textbox).getActionView();
	searchView.setOnQueryTextListener(new OnQueryTextListener() {
		@Override
		public boolean onQueryTextChange(String newText) {
			searchLibrary(newText);
			return false;
		}
		@Override
		public boolean onQueryTextSubmit(String query) { return false; }
	});
	searchView.setOnCloseListener(new OnCloseListener() {
		@Override
		public boolean onClose() {
			System.out.println("Testing. 1, 2, 3...");
			return false;
		}
	});
	return true;
}

The search works great and every is working except for the OnCloseListener. Nothing is being printed to Logcat. Here's the Logcat for when I'm pressing the "Close" button:

02-17 13:01:52.914: I/TextType(446): TextType = 0x0
02-17 13:01:57.344: I/TextType(446): TextType = 0x0
02-17 13:02:02.944: I/TextType(446): TextType = 0x0

I've looked through the documentation and samples, but nothing seemed to change it. I'm running it on a Asus Transformer Prime and a Galaxy Nexus, both on Ice Cream Sandwich. Any ideas?

Update:

Yes - System.out.println() does work. Here's proof:

   @Override
 public boolean onQueryTextChange(String newText) {
    System.out.println(newText + "hello");
    searchLibrary(newText);
    return false;
 }

Results in this Logcat:

02-17 13:04:20.094: I/System.out(21152): hello
02-17 13:04:24.914: I/System.out(21152): thello
02-17 13:04:25.394: I/System.out(21152): tehello
02-17 13:04:25.784: I/System.out(21152): teshello
02-17 13:04:26.064: I/System.out(21152): testhello

Android Solutions


Solution 1 - Android

I also meet this problem, and I have no choice but give up "oncloselistener". Instead, you can get your menuItem, then setOnActionExpandListener. Then override unimplents methods.

@Override
public boolean onMenuItemActionExpand(MenuItem item) {
	// TODO Auto-generated method stub
	Log.d("*******","onMenuItemActionExpand");
	return true;
}

@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
	//do what you want to when close the sesarchview
	//remember to return true;
	Log.d("*******","onMenuItemActionCollapse");
	return true;
}

Solution 2 - Android

For Android API 14+ (ICS and greater) use this code:

// When using the support library, the setOnActionExpandListener() method is
// static and accepts the MenuItem object as an argument
MenuItemCompat.setOnActionExpandListener(menuItem, new OnActionExpandListener() {
    @Override
    public boolean onMenuItemActionCollapse(MenuItem item) {
        // Do something when collapsed
        return true;  // Return true to collapse action view
    }

    @Override
    public boolean onMenuItemActionExpand(MenuItem item) {
        // Do something when expanded
        return true;  // Return true to expand action view
    }
});

For more information: http://developer.android.com/guide/topics/ui/actionbar.html#ActionView

Ref: onActionCollapse/onActionExpand

Solution 3 - Android

For this problem I came up with something like this,

private SearchView mSearchView;

@TargetApi(14)
@Override
public boolean onCreateOptionsMenu(Menu menu)
{

	MenuInflater inflater = getMenuInflater();
	inflater.inflate(R.menu.conversation_index_activity_menu, menu);

	mSearchView = (SearchView) menu.findItem(R.id.itemSearch).getActionView();

	MenuItem menuItem = menu.findItem(R.id.itemSearch);

	int currentapiVersion = android.os.Build.VERSION.SDK_INT;
	if (currentapiVersion >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH)
	{
		menuItem.setOnActionExpandListener(new OnActionExpandListener()
		{

			@Override
			public boolean onMenuItemActionCollapse(MenuItem item)
			{
				// Do something when collapsed
				Log.i(TAG, "onMenuItemActionCollapse " + item.getItemId());
				return true; // Return true to collapse action view
			}

			@Override
			public boolean onMenuItemActionExpand(MenuItem item)
			{
				// TODO Auto-generated method stub
				Log.i(TAG, "onMenuItemActionExpand " + item.getItemId());
				return true;
			}
		});
	} else
	{
		// do something for phones running an SDK before froyo
		mSearchView.setOnCloseListener(new OnCloseListener()
		{

			@Override
			public boolean onClose()
			{
				Log.i(TAG, "mSearchView on close ");
				// TODO Auto-generated method stub
				return false;
			}
		});
	}


	return super.onCreateOptionsMenu(menu);

}

Solution 4 - Android

I ran into same problem on android 4.1.1. Looks like it is a known bug: https://code.google.com/p/android/issues/detail?id=25758

Anyway, as a workaround i used state change listener (when SearchView is detached from action bar, it is also closed obviously).

view.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
                
    @Override
    public void onViewDetachedFromWindow(View arg0) {
        // search was detached/closed
    }
                
    @Override
    public void onViewAttachedToWindow(View arg0) {
        // search was opened
    }
});

Above code worked well in my case.


I post same answer here: https://stackoverflow.com/a/24573266/2162924

Solution 5 - Android

I ended up using a bit of a hack, that works well for my purpose - not sure it'll work with all purposes. Anyway, I'm doing a check to see if the search query is empty. This is not really related to the SearchView's OnCloseListener though - that still doesn't work!

searchView.setOnQueryTextListener(new OnQueryTextListener() {
			@Override
			public boolean onQueryTextChange(String newText) {
				if (newText.length() > 0) {
					// Search
				} else {
					// Do something when there's no input
				}
				return false;
			}
			@Override
			public boolean onQueryTextSubmit(String query) { return false; }
		});

Solution 6 - Android

Well, this solved my problem:

Menu item with showAsAction="always"

<item
    android:id="@+id/action_search"
    android:icon="@drawable/ic_action_search"
    android:title="Search"
    app:actionViewClass="android.support.v7.widget.SearchView"
    app:showAsAction="always"/>

and in activity

searchView.setOnCloseListener(new OnCloseListener() {

		@Override
		public boolean onClose() {

			Log.i("SearchView:", "onClose");
			searchView.onActionViewCollapsed();
			return false;
		}
	});

Solution 7 - Android

In order to make the OnCloseListener work, make sure that showAsAction is set to always in the search menu item.

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:tools="http://schemas.android.com/tools"
      tools:context=".SearchActivity">

    <item
        android:id="@+id/search"
        android:title="@string/search"
        android:icon="@drawable/ic_search_toolbar"
        app:showAsAction="always"
        app:actionViewClass="android.support.v7.widget.SearchView"/>
</menu>

Solution 8 - Android

Create the menu item with the app:showAsAction set to always.

<item   
 android:id="@+id/action_search"  
 android:title="..."  
 android:icon="..."  
 app:actionViewClass="android.support.v7.widget.SearchView"  
 app:showAsAction="always"/>

When creating the SearchView in the onCreateOptionsMenu method do something similar

inflater.inflate(R.menu.menu_search, menu);
final MenuItem item = menu.findItem(R.id.action_search);
final SearchView search = (SearchView) item.getActionView();
search.setQueryHint(getString(R.string.search_brand_item));
search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
  @Override
  public boolean onQueryTextSubmit(String query) {
    // add your code
    return false;
  }

  @Override
  public boolean onQueryTextChange(String newText) {
    // add your code 
    return false;
  }
});
search.setOnCloseListener(new SearchView.OnCloseListener() {
  @Override
  public boolean onClose() {
    // add your code here
    return false;
  }
});
search.setIconifiedByDefault(true); // make sure to set this to true

The search.setIconifiedByDefault(true) needs to be set to true to call the onClose() method on the SearchView.OnCloseListener() created above.

Solution 9 - Android

I have encountered the same problem with onCloseListener not invoking for the SearchView. Understand from the bug issue raised in 25758, and some postings I have read, to invoke onCloseListener, you need to set:

searchView.setIconifiedByDefault(true);

But for my case I wanted to have the search view opened & not iconified all the time. I manage to resolve this by adding one more line below:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
	MenuInflater inflater = getMenuInflater();
	inflater.inflate(R.menu.search_bar, menu);
	SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
	searchView = (SearchView) menu.findItem(R.id.search).getActionView();
	searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
	searchView.setOnQueryTextListener(queryTextListener);
	searchView.setIconifiedByDefault(true);
	searchView.setIconified(false);
	return true;
}

The searchView.setIconified(false) will cause the searchView to open up, despite setting the default to iconified to true in the previous line. In this way, I managed to have both a SearchView that opens up all the time & having it invoke the onCloseListener.

Solution 10 - Android

    searchView.setOnCloseListener {
        d("click", "close clicked")
        return@setOnCloseListener false
    }

if you click on close searchView ->

D/click: close clicked

Solution 11 - Android

For MenuItemCompat problem I added ViewTreeObserver to track the visibility state. You can check my answer here: https://stackoverflow.com/a/28762632/1633609

Solution 12 - Android

I used the SearchView close button and set a setOnClickListener on it

searchView.findViewById<ImageView>(R.id.search_close_btn).setOnClickListener {
    searchView.setQuery("", false)
    searchView.clearFocus()
}

Solution 13 - Android

The reason the OnCloseListener is not called is because there is a bug in the Android code -- the listener is only called if you also call setIconifiedByDefault(true).

Solution 14 - Android

seems an old thread already, but I thought I got the same problem API 18 in the first beginning. After googled around, found this thread, another hour read the javadoc tried and errored for something I don't pretend fully understand in javadoc, the following work for me now:

searchView.setIconifiedByDefault(true);

   // OnQueryTextListener
   @Override
   public boolean onQueryTextSubmit(String query) {
      Log.d(tag, "onQueryTextSubmit: " + query);
      return true;
   }

   @Override
   public boolean onQueryTextChange(String query) {
      Log.d(tag, "onQueryTextChange: " + query);
      return true;
   }

   // OnCloseListener
   @Override
   public boolean onClose() {
      Log.w(tag, "onClose: ");
      return false;
   }

I played with true/false a bit, that somehow makes the difference, and it works for me now. Hopefully, it could save someone time.

Solution 15 - Android

It's a workaround but has worked for me

  searchView.setOnQueryTextListener(new android.widget.SearchView.OnQueryTextListener() {

                String lastText;

                @Override
                public boolean onQueryTextChange(final String newText) {
                    if (lastText != null && lastText.length() > 1 && newText.isEmpty()) {
                        // close ctn clicked
                      
                        return true;
                    }
}
           

Solution 16 - Android

I encountered this issue while trying to detect the showing/dismissal of the SearchView. I ended up using a different listener and it worked for what I need:

        setOnQueryTextFocusChangeListener { _, hasFocus ->
            if (hasFocus) {
                // SearchView is being shown
            } else {
                // SearchView was dismissed
            }
        }

Solution 17 - Android

There is no console in Android to log to. Instead, use the android logging framework:

Log.d("Test Tag", "Testing.  1, 2, 3...");

See also this question: https://stackoverflow.com/questions/2220547/why-doesnt-system-out-println-work-in-android

Solution 18 - Android

There are two common patterns for SearchView.setOnCloseListener(). This is really true of all listeners, but I'm addressing your question specifically. The first way is to create a listener function and attach it to a member variable, and the second is to make the class implement the interface and have the handler be a member function.

Creating a listener object looks like this:

private SearchView mSearchView;
private final SearchView.OnCloseListener mOnCloseListener = 
    new SearchView.OnCloseListener() {
        public boolean onClose() {
            doStuff();
            return myBooleanResult;
        }
    };
mSearchView.setOnCloseListener(mOnCloseListener);

Implementing listener at class level looks like this:

public class MyClass implements OnCloseListener {
    private SearchView mSearchView;

    public MyClass(...) {
        mSearchView.setOnCloseListener(this);
    }

    @Override
    public boolean onClose() {
        doStuff();
        return false;
    }
}

I have not seen any examples that create the OnCloseListener ad-hoc, as you did in your question.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMichell BakView Question on Stackoverflow
Solution 1 - Androidniki huangView Answer on Stackoverflow
Solution 2 - AndroidlomzaView Answer on Stackoverflow
Solution 3 - AndroidBen BensonView Answer on Stackoverflow
Solution 4 - AndroidDarioView Answer on Stackoverflow
Solution 5 - AndroidMichell BakView Answer on Stackoverflow
Solution 6 - AndroidSushantView Answer on Stackoverflow
Solution 7 - AndroidJulio BettaView Answer on Stackoverflow
Solution 8 - AndroidRay HunterView Answer on Stackoverflow
Solution 9 - AndroidgklView Answer on Stackoverflow
Solution 10 - AndroidOleksandr YahnenkoView Answer on Stackoverflow
Solution 11 - AndroidSir NIkolay Cesar The FirstView Answer on Stackoverflow
Solution 12 - AndroidAlexanderView Answer on Stackoverflow
Solution 13 - AndroidJoseph EarlView Answer on Stackoverflow
Solution 14 - AndroidSeanView Answer on Stackoverflow
Solution 15 - AndroidNativView Answer on Stackoverflow
Solution 16 - AndroidPsylockeView Answer on Stackoverflow
Solution 17 - AndroidChris KnightView Answer on Stackoverflow
Solution 18 - AndroidSparkyView Answer on Stackoverflow