1. ホーム
  2. android

[解決済み] サーチビューウィジェットの背景の描画を変更する

2022-08-04 11:12:26

質問

Android のアクションバー検索ビューウィジェットに配置されている描画オブジェクトを変更しようとしています。

現在、以下のようになります。

となっていますが、背景の青いdrawableを赤い色に変更する必要があります。

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

誰か、これを変更するための正しい方向を示してくれませんか?

どのように解決するのですか?

導入

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

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

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

NOTE 以下の解決策は、id( android:id/search_plate ) にのみ依存します。 SearchView というように、子要素の探索よりも SDK のバージョンに依存しません。 searchView.getChildAt(0) の中で正しいビューに到達するために SearchView の中で正しいビューを得ることができます)、しかし、それは弾丸防止ではありません。特に、どこかのメーカーが SearchView の内部を再実装することを決定し、上記の ID を持つ要素が存在しなくなった場合、コードは動作しません。

SDKでは、テキストフィールドの背景は SearchView のテキストフィールドの背景は 九分九厘 で宣言されているので、同じようにします。あなたは、オリジナルの png の画像は 描画可能なmdpi ディレクトリにある Android の git リポジトリ . ここでは、2つの画像に注目しています。ひとつはテキストフィールドが選択されたときの状態(名前は textfield_search_selected_holo_light.9.png という名前のもの)と、そうでない場合のもの(名前は テキストフィールド_検索_デフォルト_ホログラム.9.png ).

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

注意 私は ホロライト をベースにしていますが、同じように ホロダーク . には実質的な違いはないようです。 選択状態 9-パッチは ライト ダーク のテーマがあります。ただし、9-patches では デフォルト状態 (を参照してください)。 ライト 暗い ). ですから、おそらく 選択状態 のためにローカルコピーを作成する必要はないでしょう。 暗い ライト のテーマ(両方を扱い、どちらも同じように見えるようにしたい場合を想定しています。 ホロ テーマ ). 単にローカルに1つコピーして、それを セレクタで描画可能な を両方のテーマで使用します。

さて、ダウンロードした9パッチをあなたの必要に合わせて編集する必要があります(例えば、青い色を赤い色に変更する)。次のようにしてファイルを見ることができます。 ドロー9パッチツール を使ってファイルを見て、編集後に正しく定義されているかどうかを確認してください。

を使ってファイルを編集したことがあります。 GIMP で一画素鉛筆ツールで編集したことがあります(かなり簡単です)。以下は、私がカスタマイズした フォーカス状態 :

注意 簡単のため、画像のみで mdpi の密度で表示しています。を作成する必要があります。 9-パッチ を作成する必要があります。の画像 ホロ SearchView mdpi , hdpi および 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>

上記で作成したdrawableを使用して、背景を 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 コンストラクタ の中で、レイアウトを膨らませている行があります。

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 を通してアクセスできれば最高なのですが、残念ながらそうではありません。比較のために、他の テーマ 属性を参照してください。 テーマ.xml R.attr のように テキスト外観 または 選択可能な項目の背景 . もし 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 にコードでアクセスしなければならないことがわかりました。しかし、それがどのように見えるべきかはまだ分かっていません。要するに、デフォルトのテーマで値として使われている drawable を探せばいいのです。 テキストフィールド_searchview_holo_dark.xml テキストフィールド_searchview_holo_light.xml . コンテンツを見てみると、drawable は selector で、ビューの状態に応じて他の 2 つの drawable (これらは後で 9-patch になる) を参照しています。ほぼすべてのバージョンの Android で使用されている 9-patch drawable は、次のサイトで見ることができます。 androiddrawables.com にあります。

カスタマイズ

の青い線は、私たちが認識している 9パッチのうちの1つ で青い線を認識したので、そのローカルコピーを作成し、好きなように色を変更します。