草庐IT

android - 更改 searchview 小部件的背景可绘制

coder 2023-05-07 原文

我正在尝试更改位于 Android 操作栏搜索 View 小部件中的可绘制对象。

目前它看起来像这样:


但我需要将可绘制的蓝色背景更改为红色。

除了滚动我自己的搜索小部件之外,我已经尝试了很多东西,但似乎没有任何效果。

有人可以指出我改变这一点的正确方向吗?

最佳答案

介绍

不幸的是,无法设置 SearchView使用 XML 中的主题、样式和继承的文本字段样式 can do with background of items in ActionBar dropdown .这是因为 selectableItemBackground is listed as styleableR.stylable , 而 searchViewTextField (我们感兴趣的主题属性)不是。因此,我们无法从 XML 资源中轻松访问它(您将收到 No resource found that matches the given name: attr 'android:searchViewTextField' 错误)。

从代码设置 SearchView 文本字段背景

所以,正确替换SearchView背景的唯一方法文本字段是进入它的内部,获取对基于 searchViewTextField 背景设置的 View 的访问权限并设置我们自己的。

注意:下面的解决方案仅取决于 android:id/search_plate 中元素的 id ( SearchView ) ,所以它比 child 遍历更独立于 SDK 版本(例如,使用 searchView.getChildAt(0)SearchView 内获得正确的 View ),但它不是防弹的。特别是如果某些制造商决定重新实现 SearchView 的内部结构并且不存在具有上述 id 的元素 - 代码将不起作用。

SDK中SearchView中的文本框背景通过 nine-patches 声明,所以我们会这样做。您可以在 drawable-mdpi 中找到原始 png 图像Android git repository的目录.我们对两张图片感兴趣。一种用于选择文本字段时的状态(名为 textfield_search_selected_holo_light.9.png ),另一种用于未选择的状态(名为 textfield_search_default_holo_light.9.png )。

不幸的是,即使您只想自定义聚焦状态,您也必须创建两个图像的本地副本。这是因为 textfield_search_default_holo_light不存在于 R.drawable .因此它不容易通过 @android:drawable/textfield_search_default_holo_light 访问。 ,可以在下面显示的选择器中使用,而不是引用本地可绘制对象。

注意:我使用 Holo Light 主题作为基础,但你可以用 Holo Dark 做同样的事情。似乎 Light 之间的选定状态 9-patch 没有真正的区别。和 Dark主题。但是,默认状态的 9 个补丁存在差异(请参阅 LightDark )。因此,对于深色和浅色主题,可能没有必要为选定状态制作 9 个补丁的本地副本(假设您想同时处理两者,并使它们看起来与 Holo 主题中的相同)。只需制作一份本地副本并在两个主题的可绘制选择器中使用它。

现在,您需要根据需要编辑下载的 9-patch (即将蓝色更改为红色)。您可以使用 draw 9-patch tool 查看文件在编辑后检查它是否正确定义。

我使用 GIMP 编辑过文件使用一像素铅笔工具(非常简单),但您可能会使用自己的工具。这是我为聚焦状态定制的 9-patch:



注意:为简单起见,我仅使用了 mdpi 密度的图像。如果您想在任何设备上获得最佳效果,您就必须为多个屏幕密度创建 9 个补丁。全息图像 SearchView可以在 mdpi 中找到, hdpixhdpi可绘制。

现在,我们需要创建可绘制的选择器,以便根据 View 状态显示正确的图像。创建文件 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 设置背景包含文本字段的 View 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);
    }

}

最终效果

这是最终结果的屏幕截图:



我是怎么做到的

我认为值得一提的是我是如何做到这一点的,以便在自定义其他 View 时可以使用这种方法。

检查 View 布局

我已经查过了 SearchView布局看起来像。在 SearchView contructor人们可以找到一条使布局膨胀的行:
inflater.inflate(R.layout.search_view, this, true);

现在我们知道 SearchView布局在名为 res/layout/search_view.xml 的文件中.调查search_view.xml我们可以找到一个内部 LinearLayout具有 search_plate 的元素(id android.widget.SearchView$SearchAutoComplete)在它里面(看起来像我们的搜索 View 文本字段):
    <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值(value) is also set in that file .

现在,如果可以通过 R.styleable 访问此属性,那就太好了。 ,但不幸的是,事实并非如此。为了进行比较,请参阅 themes.xml 中都存在的其他主题属性。和 R.attr喜欢 textAppearanceselectableItemBackground .如 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>

应该修改什么?

现在我们知道了,我们必须访问 search_plate通过代码。但是,我们仍然不知道它应该是什么样子。简而言之,我们搜索用作默认主题值的可绘制对象:textfield_searchview_holo_dark.xmltextfield_searchview_holo_light.xml .查看内容,我们看到可绘制对象是 selector根据 View 状态引用其他两个可绘制对象(稍后出现 9 个补丁)。您可以在 androiddrawables.com 上找到(几乎)所有 Android 版本的聚合 9-patch drawable。

定制

我们认出了 one of the 9-patches 中的蓝线,因此我们创建它的本地副本并根据需要更改颜色。

关于android - 更改 searchview 小部件的背景可绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11085308/

有关android - 更改 searchview 小部件的背景可绘制的更多相关文章

  1. ruby-on-rails - Ruby on Rails 迁移,将表更改为 MyISAM - 2

    如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设

  2. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  3. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  4. ruby - Capistrano 3 在任务中更改 ssh_options - 2

    我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe

  5. ruby-on-rails - 使用 Rmagick 或 ImageMagick 在背景上放置标题 - 2

    我有一张背景图片,我想在其中添加一个文本框。我想弄清楚如何将标题放置在其顶部的正确位置。(我使用标题是因为我需要自动换行功能)。现在,我只能让文本显示在左上角,但我需要能够手动定位它的开始位置。require'RMagick'require'Pry'includeMagicktext="Loremipsumdolorsitamet"img=ImageList.new('template001.jpg')img 最佳答案 这是使用convert的ImageMagick命令行的答案。如果你想在Rmagick中使用这个方法,你必须自己移植

  6. ruby - 更改 ActiveRecord 中对象的类 - 2

    假设我有一个FireNinja我的数据库中的对象,使用单表继承存储。后来才知道他真的是WaterNinja.将他更改为不同的子类的最干净的方法是什么?更好的是,我很想创建一个新的WaterNinja对象并替换旧的FireNinja在数据库中,保留ID。编辑我知道如何创建新的WaterNinja来self现有FireNinja的对象,我也知道我可以删除旧的并保存新的。我想做的是改变现有项目的类别。我是通过创建一个新对象并执行一些ActiveRecord魔法来替换行,还是通过对对象本身做一些疯狂的事情,或者甚至通过删除它并使用相同的ID重新插入来做到这一点,这是问题的一部分。

  7. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  8. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  9. ruby-on-rails - 有没有一种工具可以在编码时自动保存对文件的增量更改? - 2

    我最喜欢的Google文档功能之一是它会在我工作时不断自动保存我的文档版本。这意味着即使我在进行关键更改之前忘记在某个点进行保存,也很有可能会自动创建一个保存点。至少,我可以将文档恢复到错误更改之前的状态,并从该点继续工作。对于在MacOS(或UNIX)上运行的Ruby编码器,是否有具有等效功能的工具?例如,一个工具会每隔几分钟自动将Gitcheckin我的本地存储库以获取我正在处理的文件。也许我有点偏执,但这点小保险可以让我在日常工作中安心。 最佳答案 虚拟机有些人可能讨厌我对此的回应,但我在编码时经常使用VIM,它具有自动保存功

  10. ruby - 是否可以将 IRB 提示配置为动态更改? - 2

    我想在IRB中浏览文件系统并让提示更改以反射(reflect)当前工作目录,但我不知道如何在每个命令后进行提示更新。最终,我想在日常工作中更多地使用IRB,让bash溜走。我在我的.irbrc中试过这个:require'fileutils'includeFileUtilsIRB.conf[:PROMPT][:CUSTOM]={:PROMPT_N=>"\e[1m:\e[m",:PROMPT_I=>"\e[1m#{pwd}>\e[m",:PROMPT_S=>"FOO",:PROMPT_C=>"\e[1m#{pwd}>\e[m",:RETURN=>""}IRB.conf[:PROMPT_MO

随机推荐