Как изменить значок по умолчанию в SearchView, который будет использоваться в панели действий на Android?
У меня возникли проблемы с настройкой значка поиска в SearchView. С моей точки зрения, значок можно изменить в атрибутах Item, правильно? Просто проверьте код ниже.
Может кто-нибудь сказать мне, что я делаю неправильно?
Это меню, которое я использую, с моим значком пользовательского поиска icn_lupa. Но когда я запускаю приложение, я всегда получаю значок поиска по умолчанию...
<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>
Спасибо заранее.
Ответы
Ответ 1
Похоже, что actionViewClass переопределяет значок, и похоже, что вы не можете изменить его из этот класс.
У вас есть два решения:
Ответ 2
Я нашел другой способ изменить значок поиска, который идет в той же строке, что и ответ Диего Пино, но прямо в onPrepareOptionsMenu
.
В вашем menu.xml (как и раньше)
<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>
В вашей деятельности:
@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);
}
Я следовал примеру изменения текста редактирования в этом примере.
Вы должны быть в состоянии сделать это для всех значков/фонов в вашем SearchView
, чтобы найти правильный идентификатор, который вы можете проверить здесь.
Надеюсь, это поможет кому-то еще!
ОБНОВЛЕНИЕ ноябрь 2017:
С этого ответа андроид был обновлен с возможностью изменения иконки поиска через XML.
Если вы нацелены на что-либо ниже Android v21, вы можете использовать:
<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" />
Или v21 и позже:
<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" />
И есть еще больше вариантов:
closeIcon
commitIcon
goIcon
searchHintIcon
searchIcon
voiceIcon
Ответ 3
Хороший ответ от @just_user
В моем случае, поскольку я использую библиотеку appcompat v7 для SearchView + ActionBar, я немного изменил его решение, чтобы сделать его совместимым с моим проектом, он должен работать, пока вы ничего не изменили, когда добавили appcompat v7 как библиотека
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:
@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);
}
Извините за очень большой значок (я еще не изменил размер значка), но он должен работать так, как есть.
![enter image description here]()
Ответ 4
Я тоже боролся с этим, но потом случайно использовал 'collapseActionView', и это исправило это!
Теперь мой menu.xml выглядит следующим образом:
<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>
Недостатком этого является то, что на планшетах SearchView будет отображаться с левой стороны ActionBar вместо того, где находится searchicon, но я не против этого.
Ответ 5
Я определил стиль для этого.
вот мой 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"/>
и это мой стиль:
<style name="CitySearchView" parent="Base.Widget.AppCompat.SearchView">
<item name="searchIcon">@drawable/ic_more_search</item>
</style>
Что это!
После завершения этого просто взгляните на 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>
каждый элемент может быть переопределен, определяя новый стиль.
Надеюсь, что это поможет!
Ответ 6
Есть способ сделать это. Хитрость заключается в том, чтобы восстановить ImageView с помощью своего идентификатора и установить новое изображение с помощью setImageResource()
. Это решение вдохновлено на Изменение фона для виджета searchview.
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));
}
Ответ 7
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) {
}
Ответ 8
После некоторых исследований я нашел решение здесь. Фокус в том, что значок не находится в ImageView
, а в объекте 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);
Ответ 9
Обновить подсказку AutocompleteTextView для обновления значка поиска в расширенном режиме, скопированного из источника 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);
}
Ответ 10
Из API 21 вы можете изменить его в xml:
android:searchIcon="@drawable/loupe"
android:closeIcon="@drawable/x_white"
Ответ 11
для уровня api < 21, я сделал это:
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);
из этого
![enter image description here]()
к этому
![enter image description here]()
Ответ 12
<SearchView
android:searchIcon="@drawable/ic_action_search"
..../>
используйте тег searchIcon xml
Ответ 13
В меню 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"/>
и создайте 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"/>
затем в активности onCreateOptionsMenu
или onPrepareOptionsMenu
:
SearchView searchView = (SearchView) menu.findItem(R.id.menu_filter).getActionView();
searchView.setOnQueryTextListener(this);
Ответ 14
Есть три значка увеличительного стекла. два из них отображаются, когда IconizedByDefault истинно (тот, который показан перед нажатием, и один отображается в "подсказке" ), и один отображается все время, когда IconizedByDefault является ложным. все поля являются частными, поэтому их можно получить по их xml-идентификатору. (большая часть кода упоминается отдельно в других ответах в этом сообщении)
когда IconizedByDefault истинно, измените значок в подсказке (который отображается только после нажатия значка):
mSearchSrcTextView = (SearchAutoComplete)findViewById(R.id.search_src_text);
затем выполните то же самое, что и в исходном коде 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 был заменен на newSearchIconDrawable, который является вашим новым значком поиска.
Затем установите подсказку с помощью
mSearchSrcTextView.setHint(ssb);
Остальные 2 значка находятся в ImageView
, которые можно найти по их идентификатору.
для значка, когда searchview закрывается (когда iconizedByDefault истинно):
mSearchButton = (ImageView) findViewById(R.id.search_button);
и для того, который всегда появляется (если iconizedByDefault является ложным)
mCollapsedIcon = (ImageView) findViewById(R.id.search_mag_icon);
Ответ 15
Отчаянное решение с использованием 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
}
Надеюсь, что это поможет кому-то.
Ответ 16
Мое решение:
Используйте два файла xml файла. В одном из xmls пункт меню имеет actionView, а в другом - нет. Первоначально раздуйте свернутое меню и щелкнув элемент меню, сделайте недействительным меню и раздуйте расширенное меню xml и убедитесь, что вы вызываете 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);
}
Ответ 17
Просто назовите свой значок тем же именем, что и значок, который используется в представлении поиска. Когда он компилируется, он берет ресурс в проекте над значком в библиотеке.
Ответ 18
в меню используйте это:
app:showAsAction="collapseActionView|ifRoom"
Ответ 19
Это работает с Material Design (тема MaterialComponents) и BottomAppBar.
Если вы используете библиотеку androidx, например:
<item
android:id="@+id/sv"
android:title="@string/search"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="always" />
Вы можете создать метод и вызывать его из любого места:
/**
* 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));
}
Пример использования:
@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);
}
}
Ответ 20
Я использую библиотеку AppCompat. Да, указание android:icon="@drawable/search_icon_png"
не работает.
Поэтому я просмотрел исходный код @style/Theme.AppCompat и нашел значок, который использует андроид.
<item name="searchViewSearchIcon">@drawable/abc_ic_search</item>
Итак, если вы переименуете свой значок поиска в своих рисунках на abc_ic_search.png
, этот значок будет отображаться как первый в своем приложении, а не папке с возможностью добавления приложения.
Работает для меня:)
Используя этот подход, вы также можете настроить значки закрытия и очистки для виджета поиска.