如何更改 SearchView 上的默认图标,以便在 Android 的操作栏中使用?
Posted
技术标签:
【中文标题】如何更改 SearchView 上的默认图标,以便在 Android 的操作栏中使用?【英文标题】:How to change the default icon on the SearchView, to be use in the action bar on Android? 【发布时间】:2012-05-13 19:36:24 【问题描述】:我在自定义 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>
提前致谢。
【问题讨论】:
我认为@just_user 的答案应该被标记为正确。请查阅。 :) 最近支持库android.support.v7.widget.SearchView
可以用app:searchIcon="@drawable/ic_your_custom_icon"
设置样式
【参考方案1】:
我找到了另一种更改搜索图标的方法,该图标与 Diego Pino 的答案在同一行,但直接在 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);
我按照这个example中更改编辑文本的示例。
您应该能够对SearchView
中的所有图标/背景执行此操作,要找到正确的 ID,您可以检查 here。
希望这对其他人也有帮助!
2017 年 11 月更新:
自从这个答案以来,android 已经更新,可以通过 XML 更改搜索图标。
如果你定位低于 android v21 的任何东西,你可以使用:
<android.support.v7.widget.SearchView
android:layout_
android:layout_
app:searchIcon="@drawable/ic_search_white_24dp"
app:closeIcon="@drawable/ic_clear_white_24dp" />
或 v21 及更高版本:
<SearchView
android:layout_
android:layout_
android:searchIcon="@drawable/ic_search_white_24dp"
android:closeIcon="@drawable/ic_clear_white_24dp" />
还有更多选择:
closeIcon
commitIcon
goIcon
searchHintIcon
searchIcon
voiceIcon
【讨论】:
使用标识符“android:id/search_button”是个好主意!我在其他任何地方都找不到。非常感谢您的回答!!! 精彩 - 在找到解决方案之前搜索了高低并尝试了很多东西 - 谢谢! 谢谢,但是当我的搜索视图展开时,仍然使用系统图标。有什么想法吗? 使用 SpannableStringBuilder 更新提示。从android源复制以下, SpannableStringBuilder ssb = new SpannableStringBuilder(" "); // 对于图标 ssb.append(hintText);可绘制的 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); 我不知道如何使用您的更新版本,您也可以与我们分享您的menu.xml
吗?【参考方案2】:
@just_user 的好回答
就我而言,由于我使用的是 SearchView + ActionBar 的 appcompat v7 库,因此我稍微修改了他的解决方案以使其与我的项目兼容,只要您在添加时没有修改任何内容,它就应该可以工作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's ImageView
ImageView v = (ImageView) mSearchView.findViewById(searchImgId);
v.setImageResource(R.drawable.search_btn);
super.onPrepareOptionsMenu(menu);
请原谅图标太大(我还没有调整图标的大小),但它应该可以正常工作。
【讨论】:
我对 sherlock 库也做了同样的事情,而且效果很好。谢谢。MenuItem searchViewMenuItem = menu.findItem(R.id.search); SearchView mSearchView = (SearchView) searchViewMenuItem.getActionView(); ImageView v = (ImageView) mSearchView.findViewById(com.actionbarsherlock.R.id.abs__search_button);
v.setImageResource(R.drawable.ic_action_search);
对于 androidx:androidx.appcompat.R.id.search_button
。并使用 v.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
修复 ImageView 缩放【参考方案3】:
我也在为此苦苦挣扎,但后来我不小心使用了“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 所在的位置,但我不介意。
【讨论】:
我试过了,真的不行。展开搜索视图后,按下后退按钮不会正确关闭它。相反,旧图标出现在操作栏的左侧。需要再次按下后退按钮才能正确隐藏它。 它适用于我的测试设备 (SM-G925V),但我不确定有多少其他设备会像 Kyle Ivey 那样出现奇怪的行为。我确实有与 Mathieu Post 所说的相同的行为,即搜索在左侧而不是右侧,但这可能是因为我不知道 collapseActionView 的预期目的。【参考方案4】:我定义了一种风格来做到这一点。
这是我的 xml:
<android.support.v7.widget.SearchView
android:id="@+id/sv_search"
android:icon="@android:drawable/ic_menu_search"
android:layout_
**style="@style/CitySearchView"**
android:layout_/>
这是我的风格:
<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>
每个项目都可以通过定义新样式来覆盖。
希望对你有帮助!
【讨论】:
【参考方案5】:有办法做到这一点。诀窍是使用它的标识符恢复 ImageView 并使用setImageResource()
设置一个新图像。此解决方案的灵感来自 Changing the background drawable of 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));
【讨论】:
澄清一下,这是在搜索视图“展开”时更改默认图标。 谢谢你,我可以改变图标。【参考方案6】: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)
【讨论】:
搜索小部件展开时您的解决方案不起作用:(【参考方案7】:经过一番研究,我找到了解决方案here。诀窍是图标不在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);
【讨论】:
【参考方案8】:在菜单 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_
android:layout_
android:searchIcon="@drawable/ic_menu_filter"/>
然后在活动的onCreateOptionsMenu
或onPrepareOptionsMenu
:
SearchView searchView = (SearchView) menu.findItem(R.id.menu_filter).getActionView();
searchView.setOnQueryTextListener(this);
【讨论】:
顺便说一句,如果你想打电话给getActionView
,请使用app:actionLayout
而不是android:actionLayout
。【参考方案9】:
看起来 actionViewClass 覆盖了图标,而且您似乎无法从 this class 更改它。
你有两个解决方案:
接受它,我认为它是用户体验和平台一致性方面的最佳选择。 Define your own actionViewClass【讨论】:
是的...你是对的...实际上我的搜索图标与默认的小部件图标非常相似,但与应用程序中使用的其余图标更相似。【参考方案10】:<SearchView
android:searchIcon="@drawable/ic_action_search"
..../>
使用 searchIcon xml 标签
【讨论】:
【参考方案11】:这适用于 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);
【讨论】:
【参考方案12】: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);
【讨论】:
关于如何更改关闭图标的任何想法?【参考方案13】:从 API 21 开始,您可以在 xml 中更改它:
android:searchIcon="@drawable/loupe"
android:closeIcon="@drawable/x_white"
【讨论】:
这也适用于低于 api 级别 21 的当前兼容库(刚刚测试了 searchIcon)。工具栏和 AppCompat 库 v7:23 中的 SearchView【参考方案14】:对于 api 级别
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);
从这里
到这里
【讨论】:
【参考方案15】:共有三个放大镜图标。其中两个在 IconizedByDefault 为真时显示(一个在按下之前显示,一个在“提示”中显示),一个在 IconizedByDefault 为假时始终显示。所有字段都是私有的,因此获取它们的方法是通过它们的 xml id。 (大部分代码已经在本文的其他答案中单独提及)
当 IconizedByDefault 为 true 时,将提示中的图标(仅在按下图标后可见)更改为:
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
中,可通过其 ID 找到。
对于关闭搜索视图时的图标(当 iconizedByDefault 为 true 时):
mSearchButton = (ImageView) findViewById(R.id.search_button);
对于总是出现的那个(如果 iconizedByDefault 为 false)
mCollapsedIcon = (ImageView) findViewById(R.id.search_mag_icon);
【讨论】:
【参考方案16】:使用 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
希望它对某人有所帮助。
【讨论】:
【参考方案17】:我的解决方案: 使用两个菜单 xml 文件。在其中一个 xml 中,菜单项有一个 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);
【讨论】:
【参考方案18】:只需将您的图标命名为与搜索视图使用的图标相同的名称。编译时,它会将项目中的资源置于库中的图标之上。
【讨论】:
【参考方案19】:我使用 AppCompat 库。是的,指定 android:icon="@drawable/search_icon_png"
不起作用。
所以我查看了@style/Theme.AppCompat 的源代码,找到了android 使用的图标。
<item name="searchViewSearchIcon">@drawable/abc_ic_search</item>
因此,如果您将可绘制对象中的搜索图标重命名为abc_ic_search.png
,则此图标将首先在您的应用可绘制对象中找到,而不是在 appcompat 可绘制文件夹中。
为我工作:)
使用这种方法,您也可以自定义搜索小部件的关闭和清除图标。
【讨论】:
以上是关于如何更改 SearchView 上的默认图标,以便在 Android 的操作栏中使用?的主要内容,如果未能解决你的问题,请参考以下文章
为 Android TV 应用程序更改 BrowseFragment 的 SearchView 默认图标?