How to change the default icon in SearchView to be used in the action bar on Android?

I'm having trouble setting up the search icon in SearchView. From my point of view, the icon can be changed in the Item attributes, right? Just check the code below.

Can someone tell me what I'm doing wrong?

This is the menu I'm using with my icn_lupa custom search icon . But when I launch the application, I always get the default search icon ...

<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_search" android:title="@string/menu_search" android:icon="@drawable/icn_lupa" android:showAsAction="always" android:actionViewClass="android.widget.SearchView" /> </menu> 

Thanks in advance.

+53
android android-actionbar
May 04 '12 at 8:58 a.m.
source share
20 answers

It looks like actionViewClass is overriding the icon, and it looks like you cannot change it from this class .

You have two solutions:

  • Live with this, and I believe that this is the best option in terms of user experience and platform compliance.
  • Define your own actionViewClass
+3
May 04 '12 at 9:11 a.m.
source share

I found another way to change the search icon, which goes on the same line as Diego Pino's answer, but right in onPrepareOptionsMenu .

In your menu.xml (as before)

 <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/action_search" android:icon="@drawable/ic_action_fav" android:title="@string/action_websearch" android:showAsAction="always|never" android:actionViewClass="android.widget.SearchView" /> </menu> 

In your activity:

 @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuItem searchViewMenuItem = menu.findItem(R.id.action_search); mSearchView = (SearchView) searchViewMenuItem.getActionView(); int searchImgId = getResources().getIdentifier("android:id/search_button", null, null); ImageView v = (ImageView) mSearchView.findViewById(searchImgId); v.setImageResource(R.drawable.your_new_icon); mSearchView.setOnQueryTextListener(this); return super.onPrepareOptionsMenu(menu); } 

I followed the example of changing the edit text in this example .

You should be able to do this for all the icons / backgrounds in your SearchView to find the correct id, which you can check here .

Hope this helps someone else!

UPDATE November 2017:

With this answer, the android has been updated with the ability to change the search icon via XML.

If you are aiming for anything below Android v21, you can use:

 <android.support.v7.widget.SearchView android:layout_width="wrap_content" android:layout_height="match_parent" app:searchIcon="@drawable/ic_search_white_24dp" app:closeIcon="@drawable/ic_clear_white_24dp" /> 

Or v21 and later:

 <SearchView android:layout_width="wrap_content" android:layout_height="match_parent" android:searchIcon="@drawable/ic_search_white_24dp" android:closeIcon="@drawable/ic_clear_white_24dp" /> 

And there are even more options:

 closeIcon commitIcon goIcon searchHintIcon searchIcon voiceIcon 
+87
Aug 21 '13 at 14:43
source share

Good answer from @just_user

In my case, since I am using the appcompat v7 library for SearchView + ActionBar, I slightly changed its solution to make it compatible with my project, it should work until you change anything when you added appcompat v7 as a library

XML:

 <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:metrodeal="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/main_menu_action_search" android:orderInCategory="100" android:title="@string/search" metrodeal:showAsAction="always" metrodeal:actionViewClass="android.support.v7.widget.SearchView" android:icon="@drawable/search_btn"/> </menu> 

Java Code:

 @Override public void onPrepareOptionsMenu(Menu menu) { MenuItem searchViewMenuItem = menu.findItem(R.id.main_menu_action_search); SearchView mSearchView = (SearchView) MenuItemCompat.getActionView(searchViewMenuItem); int searchImgId = android.support.v7.appcompat.R.id.search_button; // I used the explicit layout ID of searchview ImageView ImageView v = (ImageView) mSearchView.findViewById(searchImgId); v.setImageResource(R.drawable.search_btn); super.onPrepareOptionsMenu(menu); } 

Sorry for the very large icon (I haven't resized the icon yet), but it should work as it is.

enter image description here

+36
Aug 02 '14 at 6:17
source share

I also struggled with this, but then accidentally used a 'collapseActionView', and that fixed it! Now my menu.xml looks like this:

 <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menu_search" android:title="@string/menu_search" android:showAsAction="always|withText|collapseActionView" android:actionViewClass="android.widget.SearchView" android:icon="@android:drawable/ic_menu_search" /> </menu> 

The disadvantage of this is that on tablets SearchView will be displayed on the left side of the ActionBar instead of where searchicon is located, but I am not against it.

+17
Jul 20 '13 at 13:53 on
source share

I defined a style for this.

here is my xml:

  <android.support.v7.widget.SearchView android:id="@+id/sv_search" android:icon="@android:drawable/ic_menu_search" android:layout_width="fill_parent" **style="@style/CitySearchView"** android:layout_height="wrap_content"/> 

and this is my style:

 <style name="CitySearchView" parent="Base.Widget.AppCompat.SearchView"> <item name="searchIcon">@drawable/ic_more_search</item> </style> 

What is it!

After completing this, just take a look at Base.Widget.AppCompat.SearchView.

 <style name="Base.Widget.AppCompat.SearchView" parent="android:Widget"> <item name="layout">@layout/abc_search_view</item> <item name="queryBackground">@drawable/abc_textfield_search_material</item> <item name="submitBackground">@drawable/abc_textfield_search_material</item> <item name="closeIcon">@drawable/abc_ic_clear_mtrl_alpha</item> <item name="searchIcon">@drawable/abc_ic_search_api_mtrl_alpha</item> <item name="goIcon">@drawable/abc_ic_go_search_api_mtrl_alpha</item> <item name="voiceIcon">@drawable/abc_ic_voice_search_api_mtrl_alpha</item> <item name="commitIcon">@drawable/abc_ic_commit_search_api_mtrl_alpha</item> <item name="suggestionRowLayout">@layout/abc_search_dropdown_item_icons_2line</item> </style> 

each element can be redefined, defining a new style.

Hope this helps!

+14
Apr 17 '15 at 7:40
source share

There is a way to do this. The trick is to restore the ImageView with its identifier and set a new image using setImageResource() . This solution is inspired by Changing the background for the searchview widget .

 private SearchView searchbox; private void customizeSearchbox() { setSearchHintIcon(R.drawable.new_search_icon); } private void setSearchHintIcon(int resourceId) { ImageView searchHintIcon = (ImageView) findViewById(searchbox, "android:id/search_mag_icon"); searchHintIcon.setImageResource(resourceId); } private View findViewById(View v, String id) { return v.findViewById(v.getContext().getResources(). getIdentifier(id, null, null)); } 
+13
Jun 07 '13 at 16:19
source share

SearchView searchView = (SearchView) findViewById (R.id.address_search);

  try { Field searchField = SearchView.class .getDeclaredField("mSearchButton"); searchField.setAccessible(true); ImageView searchBtn = (ImageView) searchField.get(searchView); searchBtn.setImageResource(R.drawable.search_glass); } catch (NoSuchFieldException e) { } catch (IllegalAccessException e) { } 
+6
Aug 26 '14 at 12:47 on
source share

After some research, I found a solution here . The trick is that the icon is not in the ImageView , but in the Spannable .

 // Accessing the SearchAutoComplete int queryTextViewId = getResources().getIdentifier("android:id/search_src_text", null, null); View autoComplete = searchView.findViewById(queryTextViewId); Class<?> clazz = Class.forName("android.widget.SearchView$SearchAutoComplete"); SpannableStringBuilder stopHint = new SpannableStringBuilder(" "); stopHint.append(getString(R.string.your_new_text)); // Add the icon as an spannable Drawable searchIcon = getResources().getDrawable(R.drawable.ic_action_search); Method textSizeMethod = clazz.getMethod("getTextSize"); Float rawTextSize = (Float)textSizeMethod.invoke(autoComplete); int textSize = (int) (rawTextSize * 1.25); searchIcon.setBounds(0, 0, textSize, textSize); stopHint.setSpan(new ImageSpan(searchIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // Set the new hint text Method setHintMethod = clazz.getMethod("setHint", CharSequence.class); setHintMethod.invoke(autoComplete, stopHint); 
+5
May 13 '14 at 20:27
source share

Update AutocompleteTextView tooltip to update search icon in advanced mode copied from android source,

 @Override public boolean onPrepareOptionsMenu(Menu menu) { mSearchMenuItem = menu.findItem(R.id.action_search); SearchView searchView = (SearchView) mSearchMenuItem.getActionView(); int searchImgId = getResources().getIdentifier("android:id/search_button", null, null); ImageView v = (ImageView) searchView.findViewById(searchImgId); v.setImageResource(R.drawable.search_or); int searchTextViewId = searchView.getContext().getResources().getIdentifier("android:id/search_src_text", null, null); AutoCompleteTextView searchTextView = (AutoCompleteTextView) searchView.findViewById(searchTextViewId); searchTextView.setHintTextColor(getResources().getColor(R.color.hint_color_white)); searchTextView.setTextColor(getResources().getColor(android.R.color.white)); searchTextView.setTextSize(18.0f); SpannableStringBuilder ssb = new SpannableStringBuilder(" "); // for the icon ssb.append(hintText); Drawable searchIcon = getResources().getDrawable(R.drawable.search_or); int textSize = (int) (searchTextView.getTextSize() * 1.25); searchIcon.setBounds(0, 0, textSize, textSize); ssb.setSpan(new ImageSpan(searchIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); searchTextView.setHint(ssb); return super.onPrepareOptionsMenu(menu); } 
+2
Nov 03 '14 at 19:05
source share

From API 21 you can change it in xml:

 android:searchIcon="@drawable/loupe" android:closeIcon="@drawable/x_white" 
+2
Jan 26 '15 at 9:21
source share

for api level <21, I did this:

  int searchImgId = getResources().getIdentifier("android:id/search_mag_icon", null, null); ImageView ivIcon = (ImageView) searchView.findViewById(searchImgId); if(ivIcon!=null) ivIcon.setImageResource(R.drawable.ic_search); 

from this

enter image description here

to that

enter image description here

+2
Jul 09 '15 at 4:48
source share
 <SearchView android:searchIcon="@drawable/ic_action_search" ..../> 

use searchIcon xml tag

+2
Apr 04 '16 at 19:15
source share

In the xml menu:

 <item android:id="@+id/menu_filter" android:actionLayout="@layout/menu_filter" android:icon="@drawable/ic_menu_filter" android:orderInCategory="10" android:showAsAction="always" android:title="@string/menu_filter"/> 

and create layout/menu_filter :

 <?xml version="1.0" encoding="utf-8"?> <SearchView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:searchIcon="@drawable/ic_menu_filter"/> 

then in onCreateOptionsMenu or onPrepareOptionsMenu :

 SearchView searchView = (SearchView) menu.findItem(R.id.menu_filter).getActionView(); searchView.setOnQueryTextListener(this); 
+2
Feb 28 '18 at 9:29
source share

There are three magnifying glass icons. two of them are displayed when IconizedByDefault is true (the one that is shown before clicking and one is displayed in the "tooltip"), and one is displayed all the time when IconizedByDefault is false. all fields are private, so they can be obtained by their xml-identifier. (most of the code is mentioned separately in other answers in this post)

when IconizedByDefault is true, change the icon in the tooltip (which only appears after clicking the icon):

 mSearchSrcTextView = (SearchAutoComplete)findViewById(R.id.search_src_text); 

then do the same as in the Android source code:

 final int textSize = (int) (mSearchSrcTextView.getTextSize() * 1.25); newSearchIconDrawable.setBounds(0, 0, textSize, textSize); final SpannableStringBuilder ssb = new SpannableStringBuilder(" "); ssb.setSpan(new ImageSpan(newSearchIconDrawable), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); ssb.append(hintText); 

mSearchHintIcon has been replaced with newSearchIconDrawable, which is your new search icon. Then set the hint with

 mSearchSrcTextView.setHint(ssb); 

The remaining 2 icons are located in ImageView , which can be found by their identifier. for the icon when the searchview closes (when iconizedByDefault is true):

 mSearchButton = (ImageView) findViewById(R.id.search_button); 

and for the one that always appears (if iconizedByDefault is false)

 mCollapsedIcon = (ImageView) findViewById(R.id.search_mag_icon); 
+1
Nov 21 '16 at 11:26
source share

A desperate solution using Kotlin

  val s = (searchView.getAllChildren().firstOrNull() as? LinearLayout)?.getAllChildren()?.filter { it is AppCompatImageView }?.firstOrNull() as? AppCompatImageView s?.setImageResource(R.drawable.search) 

getAllChildren:

 fun ViewGroup.getAllChildren() : ArrayList<View> { val views = ArrayList<View>() for (i in 0..(childCount-1)) { views.add(getChildAt(i)) } return views } 

Hope this helps someone.

+1
Dec 07 '17 at 11:57
source share

My solution: Use two xml files. In one of xmls, the menu item has an actionView, while in the other it does not. Initially inflate a minimized menu and by clicking a menu item, invalidate the menu and inflate the xml advanced menu and make sure you call setIconified (false);

 @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { if(!mShowSearchView) { inflater.inflate(R.menu.menu_collapsed, menu); } else { inflater.inflate(R.menu.menu_expanded, menu); MenuItem searchItem = menu.findItem(R.id.action_search); SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem); searchView.setIconified(false); searchView.setOnCloseListener(new OnCloseListener() { @Override public boolean onClose() { mShowSearchView = false; ActivityCompat.invalidateOptionsMenu(getActivity()); return false; } }); } super.onCreateOptionsMenu(menu, inflater); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.action_filter) { menu.showMenu(); } else if (item.getItemId() == R.id.action_search) { mShowSearchView = true; ActivityCompat.invalidateOptionsMenu(getActivity()); } return super.onOptionsItemSelected(item); } 
0
Aug 27 '13 at 17:07
source share

Just name your icon with the same name as the icon used in the search view. When it compiles, it takes a resource in the project above the icon in the library.

0
Jul 16 '14 at 2:06
source share

in the menu use this:

 app:showAsAction="collapseActionView|ifRoom" 
0
May 26 '19 at 15:11
source share

This works with Material Design (MaterialComponents theme) and BottomAppBar.

If you are using androidx library, for example:

  <item android:id="@+id/sv" android:title="@string/search" app:actionViewClass="androidx.appcompat.widget.SearchView" app:showAsAction="always" /> 

You can create a method and call it from anywhere:

  /** * Set SearchView Icon * @param i Drawable icon */ private void setSVIcon(int i) { ImageView iv = searchView.findViewById(androidx.appcompat.R.id.search_button); iv.setImageDrawable(ResourcesCompat.getDrawable(getResources(), i, null)); } 

Usage example:

 @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(m, menu); MenuItem mn = menu.findItem(R.id.sv); if (mn != null) { searchview = (SearchView) mn.getActionView(); setSVIcon(R.drawable.ic_sr); } } 
0
Jun 28 '19 at 23:40
source share

I am using the AppCompat library. Yes, specifying android:icon="@drawable/search_icon_png" does not work. So I looked at the source code of @ style / Theme.AppCompat and found an icon that uses android.

 <item name="searchViewSearchIcon">@drawable/abc_ic_search</item> 

So, if you rename your search icon in your drawings to abc_ic_search.png , this icon will appear as the first in your application, and not a folder with the ability to add an application. It works for me :)

Using this approach, you can also customize the close and clear icons for the search widget.

-one
Apr 03 '14 at
source share



All Articles