example - show action bar android
¿Cómo cambiar el ícono predeterminado en SearchView, para usar en la barra de acción en Android? (18)
Actualizar la sugerencia de AutocompleteTextView para actualizar el ícono de búsqueda en el modo expandido, copiado de la fuente de Android,
@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);
}
Tengo problemas para personalizar el ícono de búsqueda en SearchView. Desde mi punto de vista, el icono se puede cambiar en los atributos del artículo, ¿verdad? Solo revisa el código de abajo ...
¿Puede alguien decirme qué estoy haciendo mal?
Este es el menú que estoy usando, con mi ícono de búsqueda personalizada icn_lupa . Pero cuando ejecuto la aplicación, siempre obtengo el ícono de búsqueda predeterminado ...
<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>
Gracias por adelantado.
Buena respuesta de @just_user
En mi caso, dado que estoy usando la biblioteca appcompat v7 para SearchView + ActionBar, modifiqué un poco su solución para que sea compatible con mi proyecto, debería funcionar siempre y cuando no modificaras nada cuando agregaras appcompat v7 como biblioteca
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>
Código Java:
@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''s ImageView
ImageView v = (ImageView) mSearchView.findViewById(searchImgId);
v.setImageResource(R.drawable.search_btn);
super.onPrepareOptionsMenu(menu);
}
Disculpa por el ícono muy grande (aún no he redimensionado el ícono), pero debería funcionar como está.
Definí un estilo para hacerlo.
aquí está mi 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"/>
y este es mi estilo:
<style name="CitySearchView" parent="Base.Widget.AppCompat.SearchView">
<item name="searchIcon">@drawable/ic_more_search</item>
</style>
Eso es!
Después de terminar eso, eche un vistazo a 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>
cada elemento se puede sobrescribir al definir un nuevo estilo.
¡Espero eso ayude!
Desde API 21 puedes cambiarlo en xml:
android:searchIcon="@drawable/loupe"
android:closeIcon="@drawable/x_white"
Después de algunas investigaciones encontré la solución here . El truco es que el ícono no está en un ImageView
sino en el objeto 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);
En el menú xml:
<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"/>
y crea el 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"/>
luego en las actividades onCreateOptionsMenu
o onPrepareOptionsMenu
:
SearchView searchView = (SearchView) menu.findItem(R.id.menu_filter).getActionView();
searchView.setOnQueryTextListener(this);
Estaba luchando con esto también, pero luego accidentalmente utilicé ''collapseActionView'' y eso lo solucionó. Mi menú.xml se ve así ahora:
<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>
La desventaja de esto es que en las tabletas SearchView aparecerá en el lado izquierdo de la barra de acciones en lugar de donde está el ícono de búsqueda, pero no me importa.
Hay tres iconos de lupa. dos de ellos se muestran cuando IconizedByDefault es verdadero (uno que se muestra antes de presionar y uno se muestra en la "sugerencia") y uno se muestra todo el tiempo cuando IconizedByDefault es falso. todos los campos son privados, por lo que la forma de obtenerlos es mediante su identificación xml. (la mayoría del código se menciona por separado en otras respuestas en esta publicación ya)
cuando IconizedByDefault es verdadero, cambie el ícono en la sugerencia (que se ve solo después de presionar el ícono) de la siguiente manera:
mSearchSrcTextView = (SearchAutoComplete)findViewById(R.id.search_src_text);
luego haz lo mismo que en el código fuente de Android:
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 fue reemplazado por newSearchIconDrawable, que es su nuevo ícono de búsqueda. Luego configura la pista con
mSearchSrcTextView.setHint(ssb);
Los otros 2 iconos se encuentran en un ImageView
, que se puede encontrar por su Id. para el icono cuando la vista de búsqueda está cerrada (cuando iconizedByDefault es verdadero) do:
mSearchButton = (ImageView) findViewById(R.id.search_button);
y para el que siempre aparece (si iconizedByDefault es falso)
mCollapsedIcon = (ImageView) findViewById(R.id.search_mag_icon);
Hay una manera de hacer esto. El truco es recuperar ImageView utilizando su identificador y establecer una nueva imagen con setImageResource()
. Esta solución está inspirada en Cambiar el fondo dibujable del widget de vista de búsqueda .
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));
}
He encontrado otra manera de cambiar el ícono de búsqueda que va en la misma línea que la respuesta de Diego Pino pero directamente en onPrepareOptionsMenu
.
En su menu.xml (igual que antes)
<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>
En tu actividad:
@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);
}
Seguí el ejemplo para cambiar el texto de edición en este example .
Debería poder hacer esto para todos los iconos / fondos en su SearchView
, para encontrar el ID correcto que puede verificar here .
Espero que esto ayude a alguien más también!
ACTUALIZACIÓN noviembre de 2017:
Dado que esta respuesta de Android se ha actualizado con la posibilidad de cambiar el icono de búsqueda a través del XML.
Si apuntas a cualquier cosa debajo de v21 de Android, puedes usar:
<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" />
O v21 y más tarde:
<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" />
Y hay incluso más opciones:
closeIcon
commitIcon
goIcon
searchHintIcon
searchIcon
voiceIcon
Mi solución: use dos archivos xml de menú. En uno de los xmls, el elemento del menú tiene un actionView y en el otro no. Inicialmente infle el menú contraído y cuando se hace clic en el elemento del menú, invalide el menú e infle el xml del menú expandido y asegúrese de llamar a 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);
}
Parece que actionViewClass se superpone al icono y no parece que pueda cambiarlo de esta clase .
Tienes dos soluciones:
- Viva con esto y creo que es la mejor opción en términos de experiencia del usuario y conformidad de la plataforma.
- Define tu propia actionViewClass
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) {
}
Simplemente nombre su icono con el mismo nombre que el icono que utiliza la vista de búsqueda. Cuando compila toma el recurso en el proyecto sobre el icono en la biblioteca.
Solución desesperada usando 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
}
Espero que ayude a alguien.
Yo uso la biblioteca AppCompat. Sí, especificar android:icon="@drawable/search_icon_png"
no funciona. Así que busqué en el código fuente de @ style / Theme.AppCompat y encontré el ícono que usa Android.
<item name="searchViewSearchIcon">@drawable/abc_ic_search</item>
Por lo tanto, si cambia el nombre de su icono de búsqueda dentro de sus abc_ic_search.png
a abc_ic_search.png
, este ícono se representa como el que se encuentra primero en su aplicación, en lugar de en la carpeta dibujable de la aplicación. Funciona para mi :)
Con este enfoque, también puede personalizar los iconos cercanos y claros para el widget de búsqueda.
para el nivel de api <21, hice esto:
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);
de esto
a esto
<SearchView
android:searchIcon="@drawable/ic_action_search"
..../>
use la etiqueta searchIcon xml