更改搜索查看构件的背景绘制 [英] Changing the background drawable of the searchview widget

查看:240
本文介绍了更改搜索查看构件的背景绘制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图改变这种状况坐落在Android的动作条搜索查看插件的绘制。

目前,它看起来是这样的:

但我需要改变的蓝色背景绘制为红色。

我试过很多东西短的滚动我自己的搜索插件,但似乎没有任何工作。

有人能指出我在正确的方向改变呢?

解决方案

简介

不幸的是没有办法使用的主题,风格和继承的XML设置<​​code>搜索查看文本字段风格为您<一个href="http://stackoverflow.com/questions/9019512/how-can-i-change-the-touch-effect-color-of-the-actionbar-in-android-3-0-and-high">can做动作条中的下拉项目的背景。这是因为 selectableItemBackground <一个href="http://developer.android.com/reference/android/R.styleable.html#Theme_selectableItemBackground">is在列为设置样式 R.stylable ,而 searchViewTextField (theme属性是我们感兴趣的)不是。因此,我们不能轻易地从XML资源中访问它(你会得到一个没有资源的发现,匹配给定的名字:ATTR机器人:searchViewTextField错误)。

设置搜索查看文本字段背景从code

所以,唯一的办法搜索查看文本字段的适当替代品的背景是进入它的内部,获取访问查看具有基于<$ C $后台设置C> searchViewTextField ,并设置自己的。

注意:解决方案下面只依赖于ID(机器人:ID / search_plate )内的搜索查看,所以它比孩子更遍历SDK版本无关的(例如,使用 searchView.getChildAt(0)去右视图中的搜索查看),但它不是防弹。特别是,如果一些制造商决定重新实现搜索查看的内部和元素与上面提到的id是不是present - 在code将无法正常工作。

在SDK中,在搜索查看背景的文本字段通过<一个声明href="http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch">nine-patches,所以我们会做同样的方式。你可以在<一个原始的 PNG 的图像href="https://github.com/android/platform_frameworks_base/tree/master/core/res/res/drawable-mdpi">drawable-mdpi Android的Git仓库。我们感兴趣的是两个图像。对于一个国家,当文本字段中选择(名为<一个href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png">textfield_search_selected_holo_light.9.png)一个用于它不是(名为<一个href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png">textfield_search_default_holo_light.9.png).

不幸的是,你必须同时创建图像的本地副本,即使你想定制只的着重的状态。这是因为 textfield_search_default_holo_light 不是present在 R.drawable 。因此,它是不容易接触到 @android:绘制/ textfield_search_default_holo_light ,这可能会在选择中使用如下图所示,而不是引用本地绘制,

注意:我使用的全息光的主题为基础,但你可以做同样的全息暗的。看来,有一个在选择的状态的的<一个9补丁没有真正的区别href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/drawable-xhdpi/textfield_search_selected_holo_light.9.png">Light和<一href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/drawable-xhdpi/textfield_search_selected_holo_dark.9.png">Dark主题。然而,有在9补丁的默认状态的(见<一有差别href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/drawable-xhdpi/textfield_search_default_holo_light.9.png">Light VS <一href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/drawable-xhdpi/textfield_search_default_holo_dark.9.png">Dark).所以,也许没有必要,使9个补丁程序的本地副本选择的状态的,为的暗黑的主题(假设你想同时处理,使他们看起来都一样的的的Holo主题的)。简单地做一个本地副本,并用它的选择绘制的两个主题。

现在,您需要编辑下载的九个补丁,您的需要(即改变从蓝色变为红色)。您可以在文件中使用得出9补丁工具检查看看,如果是后正确定义编辑。

我已经编辑使用 GIMP 的一个像素的铅笔工具(pretty的简单)的文件,但你可能会使用你自己的工具。这是我定制的9补丁的聚焦状态的:

注意:为了简单起见,我用的 MDPI 的密度仅适用于图像。你必须创建的 9补丁的多个屏幕密度,如果,你想在任何设备上的最好成绩。对于图像的河洛搜索查看可以在<一个发现href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png">mdpi, <一href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png">hdpi和<一href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/drawable-xhdpi/textfield_search_selected_holo_light.9.png">xhdpi可绘制。

现在,我们需要创建绘制选择器,使基于视图状态显示正确的图像。创建文件 RES /绘制/ texfield_searchview_holo_light.xml 与以下内容:

 &LT; XML版本=1.0编码=UTF-8&GT?;

&LT;选择的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android&GT;
    &LT;项目安卓state_focused =真
        机器人:可绘制=@可绘制/ textfield_search_selected_holo_light/&GT;
    &LT;项目机器人:可绘制=@可绘制/ textfield_search_default_holo_light/&GT;
&LT; /选择器&GT;
 

我们将使用上面创建的绘制,设置背景的LinearLayout 查看保存的文本字段中搜索查看 - 它的id是机器人:ID / search_plate 。因此,这里是如何在code迅速做到这一点,在创建选项菜单时:

 公共类MainActivity延伸活动{

    @覆盖
    公共无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.activity_main);
    }

    @覆盖
    公共布尔onCreateOptionsMenu(功能菜单){
        。getMenuInflater()膨胀(R.menu.activity_main,菜单);

        //获取搜索查看由ID定义有XML布局 -  my_search_view在这种情况下,
        搜索查看搜索查看=(搜索查看)menu.findItem(R.id.my_search_view).getActionView();
        //获取ID为'search_plate - 的id是生成R档的一部分,
        //所以我们必须得到ID上运行。
        INT searchPlateId = searchView.getContext()getResources()则getIdentifier(机器人:ID / search_plate,NULL,NULL);。
        //获取search_plate的LinearLayout。
        查看searchPlate = searchView.findViewById(searchPlateId);
        //设置search_plate的背景前面定义绘制。
        sea​​rchPlate.setBackgroundResource(R.drawable.textfield_searchview_holo_light);

        返回super.onCreateOptionsMenu(菜单);
    }

}
 

最终效果

下面是最终结果的截图:

我是如何走到这

我认为这是值得metioning我是怎么到这一点,所以,这种方法可以自定义其他视图时使用。

签出视图布局

我已经签了如何搜索查看布局的模样。在<一个href="http://grep$c$c.com/file/repository.grep$c$c.com/java/ext/com.google.android/android/4.0.4_r1.2/android/widget/SearchView.java/#248">SearchView构造器人们可以发现,膨胀布局的行:

  inflater.inflate(R.layout.search_view,这一点,真正的);
 

现在我们知道,搜索查看布局是名为 RES /布局/ search_view.xml 。展望<一个href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/layout/search_view.xml#L75">search_view.xml我们可以发现一个内的LinearLayout 元素(id为 search_plate ),有 android.widget。搜索查看$ SearchAutoComplete 里面(看起来像我们这样的搜索查看文本字段):

 &LT;的LinearLayout
        机器人:ID =@ + ID / search_plate
        机器人:layout_width =WRAP_CONTENT
        机器人:layout_height =WRAP_CONTENT
        机器人:layout_weight =1
        机器人:layout_gravity =center_vertical
        机器人:方向=横向
        机器人:背景=机器人:ATTR / searchViewTextField&GT;
 

现在,我们现在的背景是基于设置当前主题的 searchViewTextField 属性。

调查属性(是很容易设定的?)

要检查 searchViewTextField 属性是如何设置的,我们研究<一href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/values/themes.xml#L343">res/values/themes.xml.有一组相关的搜索查看属性的默认主题的:

 &LT;样式名称=主题&GT;
    &LT;! - (...其他属性present这里...) - &GT;

    &LT;! - 搜索查看属性 - &GT;
    &LT;项目名称=searchDropdownBackground&GT; @android:绘制/ spinner_dropdown_background&LT; /项目&GT;
    &LT;项目名称=searchViewTextField&GT; @可绘制/ textfield_searchview_holo_dark&LT; /项目&GT;
    &LT;项目名称=searchViewTextFieldRight&GT; @可绘制/ textfield_searchview_right_holo_dark&LT; /项目&GT;
    &LT;项目名称=searchViewCloseIcon&GT; @android:绘制/ ic_clear&LT; /项目&GT;
    &LT;项目名称=searchViewSearchIcon&GT; @android:绘制/ ic_search&LT; /项目&GT;
    &LT;项目名称=searchViewGoIcon&GT; @android:绘制/ ic_go&LT; /项目&GT;
    &LT;项目名称=searchViewVoiceIcon&GT; @android:绘制/ ic_voice_search&LT; /项目&GT;
    &LT;项目名称=searchViewEditQuery&GT; @android:绘制/ ic_commit_search_api_holo_dark&LT; /项目&GT;
    &LT;项目名称=searchViewEditQueryBackground&GT; ATTR / selectableItemBackground&LT; /项目&GT;
 

我们看到,默认主题值 @绘制/ textfield_searchview_holo_dark 。对于 Theme.Light 值<一href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/values/themes.xml#L461">is还设置了文件。

现在,这将是巨大的,如果这个属性是通过 R.styleable 的访问,但,可惜事实并非如此。为了进行比较,看其他的主题的属性,这是present无论是在<一个href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/values/themes.xml">themes.xml和 R.attr 喜欢<一href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/values/themes.xml#L60">textAppearance或<一href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/values/themes.xml#L118">selectableItemBackground.如果 searchViewTextField 是present在 R.attr (和 R.stylable ),我们可以简单地使用我们的绘制选择为我们的XML整个应用程序定义主题时。例如:

 &LT;资源的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android&GT;

    &LT;样式名称=AppTheme父=机器人:Theme.Light&GT;
        &LT;项目名称=机器人:searchViewTextField&GT; @可绘制/ textfield_searchview_holo_light&LT; /项目&GT;
    &LT; /风格&GT;
&LT; /资源&GT;
 

应该怎么修改?

现在我们知道,我们必须通过code访问 search_plate 。但是,我们仍然不知道它应该是什么样子。总之,我们搜索作为默认主题值可绘制:<一href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/drawable/textfield_searchview_holo_dark.xml">textfield_searchview_holo_dark.xml和<一href="https://github.com/android/platform_frameworks_base/blob/master/core/res/res/drawable/textfield_searchview_holo_light.xml">textfield_searchview_holo_light.xml.纵观内容我们可以看到绘制的选择其中引用另外两个可绘制(发生的是9补丁以后),基于视图状态。您可以从聚集的9补丁可绘(几乎)在 androiddrawables.com

所有版本的Andr​​oid

自定义

我们认识到蓝线<一href="https://github.com/android/platform_frameworks_base/raw/android-4.0.1_r1.2/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png">one的9补丁的,所以我们创建它的本地副本,然后根据需要改变颜色。

I'm trying to change the drawable that sits in the Android actionbar searchview widget.

Currently it looks like this:

but I need to change the blue background drawable to a red colour.

I've tried many things short of rolling my own search widget, but nothing seems to work.

Can somebody point me in the right direction to changing this?

解决方案

Intro

Unfortunately there's no way to set SearchView text field style using themes, styles and inheritance in XML as you can do with background of items in ActionBar dropdown. This is because selectableItemBackground is listed as styleable in R.stylable, whereas searchViewTextField (theme attribute that we're interested in) is not. Thus, we cannot access it easily from within XML resources (you'll get a No resource found that matches the given name: attr 'android:searchViewTextField' error).

Setting SearchView text field background from code

So, the only way to properly substitute background of SearchView text field is to get into it's internals, acquire access to view that has background set based on searchViewTextField and set our own.

NOTE: Solution below depends only on id (android:id/search_plate) of element within SearchView, so it's more SDK-version independent than children traversal (e.g. using searchView.getChildAt(0) to get to the right view within SearchView), but it's not bullet-proof. Especially if some manufacturer decides to reimplement internals of SearchView and element with above-mentioned id is not present - the code won't work.

In SDK, the background for text field in SearchView is declared through nine-patches, so we'll do it the same way. You can find original png images in drawable-mdpi directory of Android git repository. We're interested in two image. One for state when text field is selected (named textfield_search_selected_holo_light.9.png) and one for where it's not (named textfield_search_default_holo_light.9.png).

Unfortunately, you'll have to create local copies of both images, even if you want to customize only focused state. This is because textfield_search_default_holo_light is not present in R.drawable. Thus it's not easily accessible through @android:drawable/textfield_search_default_holo_light, which could be used in selector shown below, instead of referencing local drawable.

NOTE: I was using Holo Light theme as base, but you can do the same with Holo Dark. It seems that there's no real difference in selected state 9-patches between Light and Dark themes. However, there's a difference in 9-patches for default state (see Light vs Dark). So, probably there's no need to make local copies of 9-patches for selected state, for both Dark and Light themes (assuming that you want to handle both, and make them both look the same as in Holo Theme). Simply make one local copy and use it in selector drawable for both themes.

Now, you'll need to edit downloaded nine-patches to your need (i.e. changing blue color to red one). You can take a look at file using draw 9-patch tool to check if it is correctly defined after your edit.

I've edited files using GIMP with one-pixel pencil tool (pretty easy) but you'll probably use the tool of your own. Here's my customized 9-patch for focused state:

NOTE: For simplicity, I've used only images for mdpi density. You'll have to create 9-patches for multiple screen densities if, you want the best result on any device. Images for Holo SearchView can be found in mdpi, hdpi and xhdpi drawable.

Now, we'll need to create drawable selector, so that proper image is displayed based on view state. Create file res/drawable/texfield_searchview_holo_light.xml with following content:

<?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>

We'll use the above created drawable to set background for LinearLayout view that holds text field within SearchView - its id is android:id/search_plate. So here's how to do this quickly in code, when creating options menu:

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);
    }

}

Final effect

Here's the screenshot of the final result:

How I got to this

I think it's worth metioning how I got to this, so that this approach can be used when customizing other views.

Checking out view layout

I've checked how SearchView layout looks like. In SearchView contructor one can find a line that inflates layout:

inflater.inflate(R.layout.search_view, this, true);

Now we know that SearchView layout is in file named res/layout/search_view.xml. Looking into search_view.xml we can find an inner LinearLayout element (with id search_plate) that has android.widget.SearchView$SearchAutoComplete inside it (looks like ours search view text field):

    <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">

Now, we now that the background is set based on current theme's searchViewTextField attribute.

Investigating attribute (is it easily settable?)

To check how searchViewTextField attribute is set, we investigate res/values/themes.xml. There's a group of attributes related to SearchView in default 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>

We see that for default theme the value is @drawable/textfield_searchview_holo_dark. For Theme.Light value is also set in that file.

Now, it would be great if this attribute was accessible through R.styleable, but, unfortunately it's not. For comparison, see other theme attributes which are present both in themes.xml and R.attr like textAppearance or selectableItemBackground. If searchViewTextField was present in R.attr (and R.stylable) we could simply use our drawable selector when defining theme for our whole application in XML. For example:

<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>

What should be modified?

Now we know, that we'll have to access search_plate through code. However, we still don't know how it should look like. In short, we search for drawables used as values in default themes: textfield_searchview_holo_dark.xml and textfield_searchview_holo_light.xml. Looking at content we see that the drawable is selector which reference two other drawables (which occur to be 9-patches later on) based on view state. You can find aggregated 9-patch drawables from (almost) all version of Android on androiddrawables.com

Customizing

We recognize the blue line in one of the 9-patches, so we create local copy of it and change colors as desired.

这篇关于更改搜索查看构件的背景绘制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆