126

Androidアクションバーのsearchviewウィジェットにあるドローアブルを変更しようとしています。

現在、次のようになっています。 ここに画像の説明を入力してください

しかし、描画可能な青い背景を赤い色に変更する必要があります。

自分の検索ウィジェットをロールする以外に多くのことを試しましたが、何も機能しないようです。

誰かが私をこれを変える正しい方向に向けることができますか?

4

12 に答える 12

259

イントロ

残念ながら、ActionBarドロップダウンの項目の背景で行うことができるようSearchViewに、XMLのテーマ、スタイル、および継承を使用してテキストフィールドのスタイルを設定する方法はありません。これは、がスタイル可能としてリストされているのに対し、(関心のあるテーマ属性)はそうではないためです。したがって、XMLリソース内から簡単にアクセスすることはできません(エラーが発生します)。selectableItemBackground R.stylablesearchViewTextFieldNo resource found that matches the given name: attr 'android:searchViewTextField'

コードからSearchViewテキストフィールドの背景を設定する

したがって、テキストフィールドの背景を適切に置き換える唯一の方法は、SearchViewテキストフィールドの内部に入り、背景が設定されているビューへのアクセスを取得しsearchViewTextField、独自に設定することです。

注:android:id/search_plate以下の解決策は、内の要素のid()のみに依存するSearchViewため、子トラバーサルよりもSDKバージョンに依存しません(たとえばsearchView.getChildAt(0)、内の正しいビューに到達するために使用しますSearchView)が、防弾ではありません。特に、一部のメーカーがの内部を再実装することを決定しSearchView、上記のIDを持つ要素が存在しない場合、コードは機能しません。

SDKでは、のテキストフィールドの背景は9つのパッチSearchViewで宣言されるため、同じ方法で行います。オリジナルのpng画像は、 Androidgitリポジトリのdrawable-mdpiディレクトリにあります。2つの画像に興味があります。1つはテキストフィールドが選択されたときの状態(textfield_search_selected_holo_light.9.pngという名前)と、選択されていない場所(textfield_search_default_holo_light.9.pngという名前)です。

残念ながら、フォーカスされた状態のみをカスタマイズする場合でも、両方の画像のローカルコピーを作成する必要があります。これは、 R.drawabletextfield_search_default_holo_lightに存在しないためです。したがって、ローカルのドローアブルを参照する代わりに、以下に示すセレクターで使用できる、を介して簡単にアクセスすることはできません。@android:drawable/textfield_search_default_holo_light

注:ベースとしてHolo Lightテーマを使用していましたが、 HoloDarkでも同じことができます。ライトテーマとダークテーマの間で、選択された状態9パッチに実際の違いはないようです。ただし、デフォルト状態の9パッチには違いがあります(ライトダークを参照)。したがって、おそらく、ダークテーマとライトテーマの両方について、選択した状態の9パッチのローカルコピーを作成する必要はありません(両方を処理し、両方をホロテーマと同じように見せたいと仮定します)。ローカルコピーを1つ作成して、両方のテーマで描画可能なセレクター。

次に、ダウンロードした9つのパッチを必要に応じて編集する必要があります(つまり、青い色を赤い色に変更します)。描画9パッチツールを使用してファイルを調べ、編集後にファイルが正しく定義されているかどうかを確認できます。

私は1ピクセルの鉛筆ツール(非常に簡単)でGIMPを使用してファイルを編集しましたが、おそらく独自のツールを使用するでしょう。これがフォーカスされた状態のためにカスタマイズされた9パッチです:

ここに画像の説明を入力してください

注:簡単にするために、 mdpi密度の画像のみを使用しました。どのデバイスでも最高の結果が必要な場合は、複数の画面密度に対して9つのパッチを作成する必要があります。Holo の画像はSearchViewmdpihdpixhdpiのドローアブルにあります。

次に、ビューの状態に基づいて適切な画像が表示されるように、描画可能なセレクターを作成する必要があります。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-その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で、レイアウトを膨らませる線を見つけることができます。

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を介してアクセスできれば素晴らしいのですが、残念ながらそうではありません。比較のために、textAppearanceselectableItemBackgroundなど、 themes.xmlR.attrの両方に存在する他のテーマ属性を参照してください。(および)に存在する場合は、アプリケーション全体のテーマをXMLで定義するときに、ドローアブルセレクターを使用するだけで済みます。例えば:searchViewTextFieldR.attrR.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、ビューの状態に基づいて、他の2つのドローアブル(後で9パッチになる)を参照していることがわかります。androiddrawables.comで、(ほぼ)すべてのバージョンのAndroidから集約された9パッチのドローアブルを見つけることができます。

カスタマイズ

9つのパッチの1つで青い線を認識しているので、そのローカルコピーを作成し、必要に応じて色を変更します。

于 2012-07-26T12:56:37.710 に答える
33

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);
}
于 2014-01-22T18:32:17.817 に答える
14

メソッドは次の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

ここに画像の説明を入力してください

于 2012-07-26T13:25:54.033 に答える
13

上記のソリューションはActionBarSherlock4.2では機能しないため、Android2.xとの下位互換性はありません。ActionBarSherlock4.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));
}
于 2012-11-20T15:53:46.140 に答える
5

私もこれを行うのに疲れていて、v7を使用しています。searchPlate経由を取得しようとするとアプリケーションがクラッシュしたので、次のgetIdentifier()ようにしました。

View searchPlate = searchView.findViewById(android.support.v7.appcompat.R.id.search_plate);
于 2015-04-03T22:05:47.790 に答える
4

アップデート

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);
        }
    }
于 2019-02-28T11:10:34.410 に答える
3

私も同じ問題に直面しました。appcompatv7ライブラリを使用し、カスタムスタイルを定義しました。ドローアブルフォルダに、次のような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"/>

アクティビティは、ActivityではなくActionBarActivityを拡張する必要があります。

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

于 2014-09-17T09:11:05.070 に答える
2

まず、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);
...
    }
于 2012-07-26T07:16:11.993 に答える
1
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>
于 2014-12-30T14:37:20.767 に答える
1

私はそれについてたくさん掘り下げていました、そして最終的に私はこの解決策を見つけました、そしてそれは私のために働きます!
あなたはこれを使うことができます

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アイコンが変更されます。

それが役に立てば幸い!

于 2020-06-28T12:03:04.823 に答える
0

この投稿の最後に、これがxamarinフォームに適用される画像で説明しました。でもAndroidのsearchviewのソースコードに基づいているので理解できると思います

xamarinフォームで検索バーのキャンセルボタンの画像を変更する方法

于 2018-07-12T03:58:27.603 に答える
0

このように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>
于 2019-03-15T17:10:27.420 に答える