我正在尝试更改坐在Android actionbar searchview小部件中的drawable。
当前看起来像这样:
但是我需要将可绘制的蓝色背景更改为红色。
除了滚动我自己的搜索小部件,我还尝试了很多事情,但是似乎没有任何效果。
有人可以指出我正确的方向来改变这一点吗?
SearchView
背景情况下是不可能的,因为它无法通过提供R.styleable
。我在下面的回答描述了如何在代码中做到这一点。
我正在尝试更改坐在Android actionbar searchview小部件中的drawable。
当前看起来像这样:
但是我需要将可绘制的蓝色背景更改为红色。
除了滚动我自己的搜索小部件,我还尝试了很多事情,但是似乎没有任何效果。
有人可以指出我正确的方向来改变这一点吗?
SearchView
背景情况下是不可能的,因为它无法通过提供R.styleable
。我在下面的回答描述了如何在代码中做到这一点。
Answers:
不幸的是,无法像在ActionBar下拉列表中使用项目背景那样,使用SearchView
XML中的主题,样式和继承来设置文本字段样式。这是因为被列为设置样式的,而(theme属性是我们感兴趣的)没有。因此,我们无法从XML资源中轻松访问它(您会得到一个错误)。selectableItemBackground
R.stylable
searchViewTextField
No resource found that matches the given name: attr 'android:searchViewTextField'
因此,正确替换SearchView
文本字段背景的唯一方法是进入其内部,获取对基于其背景设置的视图的访问权searchViewTextField
并设置我们自己的视图。
注意:以下解决方案仅取决于中android:id/search_plate
的element的id()SearchView
,因此与子遍历相比,SDK版本更独立(例如,searchView.getChildAt(0)
用于获得正确的视图SearchView
),但这不是防弹的。特别是如果某些制造商决定重新实现的内部结构,SearchView
并且不存在具有上述id的元素-该代码将无法正常工作。
在SDK中,文本字段的背景SearchView
是通过9个补丁声明的,因此我们将以相同的方式进行操作。您可以在Android git仓库的drawable-mdpi目录中找到原始png图像。我们对两个图像感兴趣。一种是在选择文本字段时的状态(名为textfield_search_selected_holo_light.9.png),另一种是在未选择文本字段的状态下(名为textfield_search_default_holo_light.9.png)。
不幸的是,即使您只想自定义聚焦状态,也必须创建两个图像的本地副本。这是因为R.drawable中textfield_search_default_holo_light
不存在。因此,通过不能轻松访问它,可以在下面显示的选择器中使用它,而不是引用局部可绘制对象。@android:drawable/textfield_search_default_holo_light
注意:我使用Holo Light主题作为基础,但是您可以对Holo Dark进行相同的操作。似乎有一个在没有真正的区别选中状态之间的9补丁轻和黑暗的主题。但是,默认状态的 9个补丁有所不同(请参阅“ 浅色”与“ 深色”)。因此,对于深色和浅色主题,都无需为所选状态制作9个补丁的本地副本(假设您要同时处理这两个主题,并使它们看上去都与Holo Theme中的主题相同)。只需制作一个本地副本并在其中使用两个主题均可选择的选择器。
现在,您需要根据需要编辑下载的九个补丁(即,将蓝色更改为红色)。您可以使用draw 9-patch工具查看文件,以检查编辑后是否正确定义了文件。
我已经使用GIMP和一像素铅笔工具(非常简单)来编辑文件,但是您可能会使用自己的工具。这是我针对焦点状态定制的9个补丁:
注意:为简单起见,我仅使用mdpi密度的图像。如果要在任何设备上获得最佳效果,则必须为多个屏幕密度创建9个补丁。Holo的 图像SearchView
可以在mdpi,hdpi和xhdpi drawable中找到。
现在,我们需要创建可绘制的选择器,以便根据视图状态显示正确的图像。创建res/drawable/texfield_searchview_holo_light.xml
具有以下内容的文件:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true"
android:drawable="@drawable/textfield_search_selected_holo_light" />
<item android:drawable="@drawable/textfield_search_default_holo_light" />
</selector>
我们将使用上面创建的drawable为LinearLayout
内部包含文本字段的视图设置背景SearchView
-其ID为android:id/search_plate
。因此,这是创建选项菜单时如何在代码中快速完成此操作的方法:
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
// Getting SearchView from XML layout by id defined there - my_search_view in this case
SearchView searchView = (SearchView) menu.findItem(R.id.my_search_view).getActionView();
// Getting id for 'search_plate' - the id is part of generate R file,
// so we have to get id on runtime.
int searchPlateId = searchView.getContext().getResources().getIdentifier("android:id/search_plate", null, null);
// Getting the 'search_plate' LinearLayout.
View searchPlate = searchView.findViewById(searchPlateId);
// Setting background of 'search_plate' to earlier defined drawable.
searchPlate.setBackgroundResource(R.drawable.textfield_searchview_holo_light);
return super.onCreateOptionsMenu(menu);
}
}
这是最终结果的屏幕截图:
我认为值得一提的是,我如何做到这一点,以便在定制其他视图时可以使用这种方法。
我检查了SearchView
布局的外观。在SearchView构造器中,可以找到使布局膨胀的线:
inflater.inflate(R.layout.search_view, this, true);
现在我们知道SearchView
布局位于名为的文件中res/layout/search_view.xml
。查看search_view.xml,我们可以找到内部有一个内部LinearLayout
元素(ID为search_plate
)android.widget.SearchView$SearchAutoComplete
(看起来像我们的搜索视图文本字段):
<LinearLayout
android:id="@+id/search_plate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:orientation="horizontal"
android:background="?android:attr/searchViewTextField">
现在,我们现在基于当前主题的searchViewTextField
属性设置背景。
为了检查searchViewTextField
属性的设置方式,我们研究了res / values / themes.xml。SearchView
默认情况下有一组与之相关的属性Theme
:
<style name="Theme">
<!-- (...other attributes present here...) -->
<!-- SearchView attributes -->
<item name="searchDropdownBackground">@android:drawable/spinner_dropdown_background</item>
<item name="searchViewTextField">@drawable/textfield_searchview_holo_dark</item>
<item name="searchViewTextFieldRight">@drawable/textfield_searchview_right_holo_dark</item>
<item name="searchViewCloseIcon">@android:drawable/ic_clear</item>
<item name="searchViewSearchIcon">@android:drawable/ic_search</item>
<item name="searchViewGoIcon">@android:drawable/ic_go</item>
<item name="searchViewVoiceIcon">@android:drawable/ic_voice_search</item>
<item name="searchViewEditQuery">@android:drawable/ic_commit_search_api_holo_dark</item>
<item name="searchViewEditQueryBackground">?attr/selectableItemBackground</item>
我们看到默认主题的值为@drawable/textfield_searchview_holo_dark
。对于Theme.Light
价值也在该文件中设置。
现在,如果可以通过R.styleable访问此属性,那就太好了,但是不幸的是,不是。为了进行比较,请参阅themes.xml和R.attr中同时存在的其他主题属性,例如textAppearance或selectableItemBackground。如果(和)中存在,则可以在为整个XML应用程序定义主题时简单地使用可绘制选择器。例如:searchViewTextField
R.attr
R.stylable
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="AppTheme" parent="android:Theme.Light">
<item name="android:searchViewTextField">@drawable/textfield_searchview_holo_light</item>
</style>
</resources>
现在我们知道,我们将必须search_plate
通过代码进行访问。但是,我们仍然不知道它的外观。简而言之,我们搜索用作默认主题中的值的可绘制对象:textfield_searchview_holo_dark.xml和textfield_searchview_holo_light.xml。通过查看内容,我们可以看到可绘制对象是selector
基于视图状态引用其他两个可绘制对象(稍后会出现9个补丁)的对象。您可以在androiddrawables.com上(几乎)所有版本的Android中找到汇总的9补丁可绘制对象
我们在9个色块之一中识别出蓝线,因此我们创建了它的本地副本并根据需要更改颜色。
SearchView
自身)。如果我将您的答案(覆盖onCreateOptionsMenu)合并到我的数据库中,可以吗?
onCreate()
方法移到另一个onCreateOptionsMenu()
方法。投票给你答案。
如果您使用的是appcompat库,则上述解决方案可能不起作用。您可能必须修改代码才能使其适用于appcompat库。
这是appcompat库的工作解决方案。
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main_menu, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
MenuItem searchMenuItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem);
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
SearchView.SearchAutoComplete searchAutoComplete = (SearchView.SearchAutoComplete)searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);
searchAutoComplete.setHintTextColor(Color.WHITE);
searchAutoComplete.setTextColor(Color.WHITE);
View searchplate = (View)searchView.findViewById(android.support.v7.appcompat.R.id.search_plate);
searchplate.setBackgroundResource(R.drawable.texfield_searchview_holo_light);
ImageView searchCloseIcon = (ImageView)searchView.findViewById(android.support.v7.appcompat.R.id.search_close_btn);
searchCloseIcon.setImageResource(R.drawable.abc_ic_clear_normal);
ImageView voiceIcon = (ImageView)searchView.findViewById(android.support.v7.appcompat.R.id.search_voice_btn);
voiceIcon.setImageResource(R.drawable.abc_ic_voice_search);
ImageView searchIcon = (ImageView)searchView.findViewById(android.support.v7.appcompat.R.id.search_mag_icon);
searchIcon.setImageResource(R.drawable.abc_ic_search);
return super.onCreateOptionsMenu(menu);
}
您的onCreateOptionsMenu
方法必须是:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.option, menu);
SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
int linlayId = getResources().getIdentifier("android:id/search_plate", null, null);
ViewGroup v = (ViewGroup) searchView.findViewById(linlayId);
v.setBackgroundResource(R.drawable.searchviewredversion);
return super.onCreateOptionsMenu(menu);
}
您的搜索项目menu_search
偏离路线的地方
这是searchviewredversion
(这是xhdpi版本):http ://img836.imageshack.us/img836/5964/searchviewredversion.png
上面的解决方案不适用于ActionBarSherlock 4.2,因此与Android 2.x不兼容。这是在ActionBarSherlock 4.2上设置SearchView背景和提示文本的工作代码:
public static void styleSearchView(SearchView searchView, Context context) {
View searchPlate = searchView.findViewById(R.id.abs__search_plate);
searchPlate.setBackgroundResource(R.drawable.your_custom_drawable);
AutoCompleteTextView searchText = (AutoCompleteTextView) searchView.findViewById(R.id.abs__search_src_text);
searchText.setHintTextColor(context.getResources().getColor(R.color.your_custom_color));
}
我也遇到了同样的问题,我使用了appcompat v7库并为其定义了自定义样式。在drawable文件夹中,放置bottom_border.xml文件,如下所示:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape >
<solid android:color="@color/blue_color" />
</shape>
</item>
<item android:bottom="0.8dp"
android:left="0.8dp"
android:right="0.8dp">
<shape >
<solid android:color="@color/background_color" />
</shape>
</item>
<!-- draw another block to cut-off the left and right bars -->
<item android:bottom="2.0dp">
<shape >
<solid android:color="@color/main_accent" />
</shape>
</item>
</layer-list>
在值文件夹中的styles_myactionbartheme.xml中:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppnewTheme" parent="Theme.AppCompat.Light">
<item name="android:windowBackground">@color/background</item>
<item name="android:actionBarStyle">@style/ActionBar</item>
<item name="android:actionBarWidgetTheme">@style/ActionBarWidget</item>
</style>
<!-- Actionbar Theme -->
<style name="ActionBar" parent="Widget.AppCompat.Light.ActionBar.Solid.Inverse">
<item name="android:background">@color/main_accent</item>
<!-- <item name="android:icon">@drawable/abc_ic_ab_back_holo_light</item> -->
</style>
<style name="ActionBarWidget" parent="Theme.AppCompat.Light">
<!-- SearchView customization-->
<!-- Changing the small search icon when the view is expanded -->
<!-- <item name="searchViewSearchIcon">@drawable/ic_action_search</item> -->
<!-- Changing the cross icon to erase typed text -->
<!-- <item name="searchViewCloseIcon">@drawable/ic_action_remove</item> -->
<!-- Styling the background of the text field, i.e. blue bracket -->
<item name="searchViewTextField">@drawable/bottom_border</item>
<!-- Styling the text view that displays the typed text query -->
<item name="searchViewAutoCompleteTextView">@style/AutoCompleteTextView</item>
</style>
<style name="AutoCompleteTextView" parent="Widget.AppCompat.Light.AutoCompleteTextView">
<item name="android:textColor">@color/text_color</item>
<!-- <item name="android:textCursorDrawable">@null</item> -->
<!-- <item name="android:textColorHighlight">@color/search_view_selected_text</item> -->
</style>
</resources>
我定义了custommenu.xml文件来显示菜单:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:com.example.actionbartheme="http://schemas.android.com/apk/res-auto" >
<item android:id="@+id/search"
android:title="@string/search_title"
android:icon="@drawable/search_buttonn"
com.example.actionbartheme:showAsAction="ifRoom|collapseActionView"
com.example.actionbartheme:actionViewClass="android.support.v7.widget.SearchView"/>
您的活动应扩展ActionBarActivity而不是Activity。
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.custommenu, menu);
}
在清单文件中:
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppnewTheme" >
有关更多信息,请参见此处:
此处http://www.jayway.com/2014/06/02/android-theming-the-actionbar/
更新资料
如果您使用的是AndroidX,则可以这样做
View searchPlate = svSearch. findViewById(androidx.appcompat.R.id.search_plate);
if (searchPlate != null) {
AutoCompleteTextView searchText = searchPlate.findViewById(androidx.appcompat.R.id.search_src_text);
if (searchText != null){
searchText.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.edittext_text_size));
searchText.setMaxLines(1);
searchText.setSingleLine(true);
searchText.setTextColor(getResources().getColor(R.color.etTextColor));
searchText.setHintTextColor(getResources().getColor(R.color.etHintColor));
searchText.setBackground(null);
}
}
首先,让我们创建一个名为search_widget_background.xml的XML文件,将其用作可绘制对象,即在可绘制目录下。
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="@color/red" />
</shape>
该可绘制对象将用作我们的搜索小部件的背景。我将颜色设置为红色,因为这就是您要的颜色,但是您可以将其设置为@color标签定义的任何颜色。您甚至可以使用为形状标签定义的属性(进行圆角处理,形成椭圆形背景等)来进一步对其进行修改。
下一步是将我们的搜索小部件的背景设置为此。这可以通过以下方式完成:
public boolean onCreateOptionsMenu(Menu menu) {
SearchView searchView = (SearchView)menu.findItem(R.id.my_search_view).getActionView();
Drawable d = getResources().getDrawable(R.drawable.search_widget_background);
searchView.setBackground(d);
...
}
SearchView
(名为search_plate
)上,而不是SearchView
自身上。请参阅我的答案以获取更多详细信息。但是,我不得不承认,我没有尝试使用@(baba tenor)的答案。
SearchView
本身始终会低于其中内部元素的背景SearchView
。LinearLayout
内部有一个SearchView
ID为ID 的视图,该视图以search_plate
蓝色下划线元素为背景。请参阅我的答案以获取详细信息。因此,对于您的解决方案,结果是整个窗口小部件的背景为蓝色,并且带有蓝色下划线。我已经在Jelly Bean上进行了测试,但是我认为SDK目标版本在这里并不重要。
public boolean onCreateOptionsMenu(Menu menu) {
........
// Set the search plate color
int linlayId = getResources().getIdentifier("android:id/search_plate", null, null);
View view = searchView.findViewById(linlayId);
Drawable drawColor = getResources().getDrawable(R.drawable.searchcolor);
view.setBackground( drawColor );
........
}
这是searchablecolor.xml文件
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape >
<solid android:color="#ffffff" />
</shape>
</item>
<!-- main color -->
<item android:bottom="1.5dp"
android:left="1.5dp"
android:right="1.5dp">
<shape >
<solid android:color="#2c4d8e" />
</shape>
</item>
<!-- draw another block to cut-off the left and right bars -->
<item android:bottom="18.0dp">
<shape >
<solid android:color="#2c4d8e" />
</shape>
</item>
</layer-list>
我在这篇文章的结尾用图片解释了这是适用于xamarin形式的。但我认为您可以理解,因为它基于android的searchview的源代码
如果要像这样“夸大Searchview”,请“ getMenuInflater()。inflate(R.menu.search_menu,menu);”。然后,您可以通过style.xml(如下所示)自定义此搜索视图。
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="searchViewStyle">@style/SearchView.ActionBar</item>
</style>
<style name="SearchView.ActionBar" parent="Widget.AppCompat.SearchView.ActionBar">
<item name="queryBackground">@drawable/drw_search_view_bg</item>
<item name="searchHintIcon">@null</item>
<item name="submitBackground">@null</item>
<item name="closeIcon">@drawable/vd_cancel</item>
<item name="searchIcon">@drawable/vd_search</item>
</style>
我对此进行了很多研究,终于找到了这个解决方案,它对我有用!
你可以用这个
如果您使用appcompat,请尝试以下操作:
ImageView searchIconView = (ImageView) searchView.findViewById(android.support.v7.appcompat.R.id.search_button);
searchIconView.setImageResource(R.drawable.yourIcon);
如果您使用androidx,请尝试以下操作:
ImageView searchIconView = (ImageView) searchView.findViewById(androidx.appcompat.R.id.search_button);
searchIconView.setImageResource(R.drawable.yourIcon);
它将更改默认的serchview图标。
希望能帮助到你!