web-dev-qa-db-ja.com

searchviewウィジェットの背景のドロアブルを変更する

Android actionbar searchviewウィジェットにあるドロウアブルを変更しようとしています。

現在、次のようになっています。 enter image description here

しかし、青い背景のドロアブルを赤い色に変更する必要があります。

私は自分の検索ウィジェットを展開する以外に多くのことを試しましたが、何もうまくいかないようです。

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

120
Martyn

イントロ

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

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

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

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

SDKでは、SearchViewのテキストフィールドの背景は nine-patches を介して宣言されているため、同じ方法で行います。元の png 画像は、 drawable-mdpi ディレクトリの Android git repository /にあります。 。 2つの画像に興味があります。 1つはテキストフィールドが選択されたときの状態(名前は textfield_search_selected_holo_light.9.png )、もう1つはそうでない場所(名前は textfield_search_default_holo_light.9) .png )。

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

注: Holo Light テーマをベースとして使用していましたが、ホロダーク selected state 9-patches between Lightの間に実際の違いはないようですDark テーマ。ただし、 default state の9パッチには違いがあります( Light vs を参照)闇 )。したがって、選択状態 Dark およびの両方に対して、9パッチのローカルコピーを作成する必要はおそらくないでしょう。 Light テーマ(両方を処理し、両方を Holo Theme と同じように見せたいと仮定します)。 1つのローカルコピーを作成し、両方のテーマの selector drawable で使用するだけです。

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

GIMP を1ピクセルの鉛筆ツール(非常に簡単)を使用してファイルを編集しましたが、おそらく独自のツールを使用するでしょう。 focused state 向けにカスタマイズした9パッチを次に示します。

enter image description here

注:簡単にするために、 mdpi 密度の画像のみを使用しました。複数の画面密度に対して 9-patches を作成する必要がある場合は、どのデバイスでも最高の結果が必要です。 Holo SearchViewの画像は、 mdpihdpi /にあります。 および xhdpi drawable。

次に、ビューステートに基づいて適切な画像が表示されるように、描画可能なセレクターを作成する必要があります。次の内容のファイル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);
    }

}

最終的な効果

最終結果のスクリーンショットは次のとおりです。

enter image description here

どうやってこれに到達した

他のビューをカスタマイズするときにこのアプローチを使用できるように、どうやってこれに到達したかを理解する価値があると思います。

ビューレイアウトのチェックアウト

SearchViewレイアウトの外観を確認しました。 SearchView contructor では、レイアウトを拡張する行を見つけることができます。

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

これで、SearchViewレイアウトがres/layout/search_view.xmlという名前のファイルにあることがわかりました。 search_view.xml を調べると、内部にsearch_plateを持つ内部LinearLayout要素(ID 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 valueの場合、 もそのファイルに設定されます

現在、この属性に R.styleable からアクセスできると便利ですが、残念ながらアクセスできません。比較のために、 themes.xmlの両方に存在する他の theme 属性を参照してください。 R.attr like textAppearance または selectableItemBackgroundsearchViewTextFieldR.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.xml および textfield_searchview_holo_light.xml 。コンテンツを見ると、ドローアブルは、ビューステートに基づいて他の2つのドローアブル(後に9パッチになる)を参照するselectorであることがわかります。集約された9パッチのドロウアブルは、 androiddrawables.com のAndroidの(ほぼ)すべてのバージョンから見つけることができます。

カスタマイズ

9-patches の青い線を認識します。そのため、そのローカルコピーを作成し、必要に応じて色を変更します。

251
vArDo

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);
}
31
Abdul Rahman

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

enter image description here

14
VinceFR

上記のソリューションはActionBarSherlock 4.2では機能しないため、Android 2.xとの後方互換性はありません。 ActionBarSherlock 4.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));
}
13
David Vávra

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

View searchPlate = searchView.findViewById(Android.support.v7.appcompat.R.id.search_plate);
5
Ido

私も同じ問題に直面しました。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/

3
Suhas Patil

最初に、drawable、つまりdrawableディレクトリの下で使用される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タグで定義された任意の色に設定できます。 shape tag (角を丸くする、楕円形の背景を作成するなど)に定義された属性を使用して、さらに変更することもできます。

次のステップでは、検索ウィジェットの背景をこれに設定します。これは次の方法で実現できます。

    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);
...
    }
2
Erol

更新

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);
        }
    }
1
Secret Coder
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>
1
M.Raheel

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

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

0
vu ledang

このような「getMenuInflater()。inflate(R.menu.search_menu、menu);」のようにSearchviewを膨らませている場合。次に、以下のように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>
0
E Player Plus