内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用
我正在试图更改Androidactionbar搜索视图小部件中的可绘制性。
目前的情况如下:
但是我需要把蓝色背景画成红色。
我尝试过很多事情,除了滚动我自己的搜索小部件,但似乎没有任何工作。
有人能指点我改变这件事的正确方向吗?
所以,正确地替换背景的唯一方法是SearchView
文本字段是进入它的内部,获取对具有背景设置的视图的访问searchViewTextField
并建立我们自己的。
注:下面的解决方案仅依赖于id(android:id/search_plate
)中的元素SearchView
,因此它比子遍历更独立于SDK版本(例如,使用searchView.getChildAt(0)
才能到达正确的视野SearchView
),但这不是防弹衣。尤其是如果一些制造商决定重新实现SearchView
并且上面提到的id元素不存在--代码不能工作。
在SDK中,SearchView
通过九块所以我们会用同样的方式。
不幸的是必须创建这两个映像的本地副本,即使只想自定义聚焦状态。这是因为textfield_search_default_holo_light
不存在,因此很难通过@android:drawable/textfield_search_default_holo_light
,可以在下面所示的选择器中使用,而不是引用本地绘图。
现在,需要根据需要编辑下载的九个补丁(即将蓝色改为红色)。若要检查编辑后是否正确定义了它,请执行以下操作。
但你可能会使用你自己的工具。这是我定制的9补丁聚焦状态:
注:为了简单起见,我只使用图像MDPI密度。你必须创造9-补丁对于多个屏幕密度,如果,希望在任何设备上的最佳结果。
现在,我们需要创建可绘制的选择器,以便根据视图状态显示正确的图像。创建文件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>
我们将使用上面创建的可绘图设置背景LinearLayout
视图中保存文本字段。SearchView
-它的身份是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
布局看起来像。
inflater.inflate(R.layout.search_view, this, true);
现在我们知道了SearchView
布局在名为res/layout/search_view.xm
我们可以找到一个内在的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
属性设置,我们将研究有一组属性与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
。
如果searchViewTextField
曾在R.attr
(和R.stylable
)在用XML为整个应用程序定义主题时,我们可以简单地使用可绘制的选择器。例如:
<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>
如果使用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); }