我正在try 更改Android actionbar searchview小部件中的drawable.
现在看起来是这样的:
但我需要把蓝色背景改成红色.
除了滚动我自己的搜索小部件,我已经try 了很多方法,但似乎没有任何效果.
有人能给我指个正确的方向来改变这一点吗?
我正在try 更改Android actionbar searchview小部件中的drawable.
现在看起来是这样的:
但我需要把蓝色背景改成红色.
除了滚动我自己的搜索小部件,我已经try 了很多方法,但似乎没有任何效果.
有人能给我指个正确的方向来改变这一点吗?
遗憾的是,您无法使用XML中的主题、样式和继承将SearchView
文本字段样式设置为can do with background of items in ActionBar dropdown.这是因为R.stylable
中的selectableItemBackground
、is listed as styleable,而searchViewTextField
(我们感兴趣的主题属性)不是.因此,我们不能从XML资源中轻松地访问它(您将得到一个No resource found that matches the given name: attr 'android:searchViewTextField'
错误).
所以,正确替换SearchView
文本字段背景的唯一方法是进入它的内部,获得对基于searchViewTextField
的背景设置的视图的访问权限,并设置我们自己的背景.
NOTE:下面的解决方案只依赖于SearchView
中元素的id(android:id/search_plate
),因此它比子遍历(例如,使用searchView.getChildAt(0)
在SearchView
中获得正确的视图)更独立于SDK版本,但它不是防弹的.尤其是如果一些制造商决定重新实现SearchView
的内部构件,并且不存在具有上述id的元件,则代码将不起作用.
在SDK中,SearchView
中文本字段的背景是通过nine-patches声明的,所以我们将以同样的方式执行.你可以在Android git repository的drawable-mdpi目录中找到最初的png张图片.我们对两张图片感兴趣.一个表示选中文本字段时的状态(命名为textfield_search_selected_holo_light.9.png),另一个表示未选中文本字段时的状态(命名为textfield_search_default_holo_light.9.png).
不幸的是,即使只想自定义focused个状态,也必须创建两个图像的本地副本.这是因为R.drawable中没有textfield_search_default_holo_light
.因此,它不容易通过@android:drawable/textfield_search_default_holo_light
访问,@android:drawable/textfield_search_default_holo_light
可以在下面所示的 Select 器中使用,而不是引用本地drawable.
我使用的是Holo Light主题作为基础,但是你也可以用Holo Dark做同样的事情.在selected state个9补丁中,Light个主题和Dark个主题似乎没有真正的区别.但是,default state的9个补丁有所不同(参见Light和Dark).因此,可能不需要为selected state、Dark和Light主题制作9个补丁的本地副本(假设您想同时处理这两个主题,并使它们看起来都与Holo Theme中的相同).只需创建一个本地副本,并在selector drawable中将其用于两个主题.
现在,您需要根据需要编辑下载的九个补丁(即将蓝色更改为红色).您可以使用draw 9-patch tool查看文件,以判断编辑后是否正确定义了该文件.
我已经用单像素的铅笔工具用GIMP编辑过文件(相当简单),但您可能会使用自己的工具.以下是我为focused state定制的9个补丁:
NOTE:为了简单起见,我只使用了mdpi密度的图像.如果你想在任何设备上获得最佳效果,就必须为多个屏幕密度创建9-patches.Holo SearchView
的图像可以在mdpi、hdpi和xhdpi中找到.
现在,我们需要创建可绘制的 Select 器,以便根据视图状态显示正确的图像.创建包含以下内容的文件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 contructor中,人们可以找到一条可以使布局inflating 的线:
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.默认Theme
中有一组与SearchView
相关的属性:
<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
等于is also set in that file.
现在,如果这个属性可以通过R.styleable访问就好了,但不幸的是,它不是.要进行比较,请参见themes.xml和R.attr中的其他theme个属性,如textAppearance或selectableItemBackground.如果R.attr
(和R.stylable
)中有searchViewTextField
,那么在用XML为整个应用程序定义主题时,我们可以简单地使用可绘制 Select 器.例如:
<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补丁可绘制内容
我们识别one of the 9-patches中的蓝线,因此我们创建它的本地副本并根据需要更改 colored颜色 .