【问题标题】:How to change the default icon on the SearchView, to be use in the action bar on Android?如何更改 SearchView 上的默认图标,以便在 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"设置样式

标签: android android-actionbar


【解决方案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_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

【讨论】:

  • 使用标识符“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_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>

每个项目都可以通过定义新样式来覆盖。

希望对你有帮助!

【讨论】:

    【解决方案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_width="wrap_content"
          android:layout_height="wrap_content"
          android:searchIcon="@drawable/ic_menu_filter"/>
      

      然后在活动的onCreateOptionsMenuonPrepareOptionsMenu

      SearchView searchView = (SearchView) menu.findItem(R.id.menu_filter).getActionView();
      searchView.setOnQueryTextListener(this);
      

      【讨论】:

      • 顺便说一句,如果你想打电话给getActionView,请使用app:actionLayout 而不是android:actionLayout
      【解决方案9】:

      看起来 actionViewClass 覆盖了图标,而且您似乎无法从 this class 更改它。

      你有两个解决方案:

      【讨论】:

      • 是的...你是对的...实际上我的搜索图标与默认的小部件图标非常相似,但与应用程序中使用的其余图标更相似。
      【解决方案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 可绘制文件夹中。 为我工作:)

                    使用这种方法,您也可以自定义搜索小部件的关闭和清除图标。

                    【讨论】:

                      猜你喜欢
                      • 2012-12-31
                      • 1970-01-01
                      • 1970-01-01
                      • 2013-09-20
                      • 2016-01-15
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2014-05-20
                      相关资源
                      最近更新 更多