定制化android.widget.SearchView

5

是否可以自定义android.widget.SearchView(我在actionBar中使用它)的布局?

我想要更改图标和文本框背景。

4个回答

17

我发现唯一的方法是使用反射。

SearchView mSearchView = (SearchView)menu.findItem(R.id.search).getActionView();
    try
    {
        Field searchField = SearchView.class.getDeclaredField("mSearchButton");
        searchField.setAccessible(true);
        ImageView searchBtn = (ImageView)searchField.get(mSearchView);
        searchBtn.setImageResource(R.drawable.search_img);
        searchField = SearchView.class.getDeclaredField("mSearchPlate");
        searchField.setAccessible(true);
        LinearLayout searchPlate = (LinearLayout)searchField.get(mSearchView);
        ((ImageView)searchPlate.getChildAt(0)).setImageResource(R.drawable.search_img);
        searchPlate.setBackgroundResource(R.drawable.edit_text_bkg);
    }
    catch (NoSuchFieldException e)
    {
        Log.e(TAG,e.getMessage(),e);
    }
    catch (IllegalAccessException e)
    {
        Log.e(TAG,e.getMessage(),e);
    }

太棒了!我甚至不知道 Java 可以做到这样的事情 :) 谢谢 Histler。 - pjanecze
对于其他好奇的人,当SearchView折叠时出现在ActionBar上的ImageView是“mSearchButton”... - Salil Pandit
SearchView.class.getDeclaredField("mSearchButton") 始终返回 null... 有什么想法吗? - Anthea
非常感谢Histier,这个答案对我帮助很大。同时也让我理解了Java反射API的强大之处。 - Chandra Sekhar
嘿@Histler,当您设置背景可绘制searchPlate.setBackgroundResource(R.drawable.textfield_searchview_holo_light);时,为什么Holo下划线距离ActionBar底部的距离比默认样式更远? - Etienne Lawlor

3
如果您使用Appcompat v7,则有一种方法可以不使用反射来完成:

声明以下样式,并仅自定义您需要自定义的属性,删除其余属性(因此它们会从父样式继承):

<style name="Widget.AppCompat.SearchView.CustomSearchView" parent="@style/Widget.AppCompat.SearchView">
    <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="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>
    <item name="searchIcon">@drawable/ic_action_search</item>
</style>

现在,在您的主题中使用相同的属性:
<item name="searchViewStyle">@style/Widget.AppCompat.SearchView.Bonial</item>

当然,你的主题必须继承自AppCompat主题之一,就像我的情况一样,它大概是这样的:
<style name="Theme.MyActionBarActivity" parent="@style/Theme.AppCompat.Light">

此外,您的活动应扩展ActionBarActivity并使用操作栏方法的“支持”版本。更多信息请参见此处
我还阅读了一篇文章,其中一个人以另一种方式声明了样式,但也使用了AppCompat v7:http://www.jayway.com/2014/06/02/android-theming-the-actionbar/

1
如果您使用的是Android原生SearchView并且想要更改搜索视图展开时出现的小搜索图标,那么您会遇到麻烦。因为searchViewSearchIcon属性是内部属性,无法使用样式进行修改。
来自SearchView类的代码片段:
private int getSearchIconId() {
    TypedValue outValue = new TypedValue();
    getContext().getTheme().resolveAttribute(com.android.internal.R.attr.searchViewSearchIcon,
            outValue, true);
    return outValue.resourceId;
}

-1
在ActionBarSherlock中:
<style name="Your_Theme" parent="@style/Theme.Sherlock">
    <item name="searchViewSearchIcon"> @drawable/ic_menu_search </item>
</style>

在Holo中:

<style name="Your_Theme" parent="@style/Theme.Light">
    <item name="android:searchViewSearchIcon"> @drawable/ic_search </item> 
</style>

1
这在 Holo 中无法工作。android:searchViewSearchIcon 不是公开可访问的。 - Kyle Ivey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接