はじめに
残念ながらSearchView
、XMLでテーマ、スタイル、継承を使用してテキストフィールドスタイルを設定する方法はありません。ActionBarドロップダウンのアイテムの背景で行うことはできます。これは、あるselectableItemBackground
styleableとしてリストされている中R.stylable
のに対し、searchViewTextField
(我々が興味を持っていることをテーマ属性)されていません。したがって、XMLリソース内から簡単にアクセスすることはできません(No resource found that matches the given name: attr 'android:searchViewTextField'
エラーが発生します)。
コードからSearchViewテキストフィールドの背景を設定する
したがって、SearchView
テキストフィールドの背景を適切に置き換える唯一の方法は、その内部にアクセスし、以下に基づいて背景が設定されているビューへのアクセスを取得することですsearchViewTextField
、独自に設定することです。
注:以下の解決策は、android:id/search_plate
内の要素のid()のみに依存するSearchView
ため、子トラバーサル(たとえば、searchView.getChildAt(0)
内の正しいビューに到達するために使用)よりもSDKバージョンに依存しませんが、完全SearchView
な保証はありません。特に、一部の製造元がSearchView
上記のidを持つ内部および要素を再実装することを決定した場合、コードは機能しません。
SDKでは、テキストフィールドの背景SearchView
は9パッチで宣言されているため、同じ方法で行います。元のpng画像は、Android gitリポジトリのdrawable-mdpiディレクトリにあります。2つの画像に興味があります。1つはテキストフィールドが選択されているときの状態(名前はtextfield_search_selected_holo_light.9.png)、1つは選択されていない場合(名前は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でも同じことができます。ライトテーマとダークテーマの選択された状態 9パッチに実際の違いはないようです。ただし、デフォルトの状態では9パッチに違いがあります(ライトとダークを参照)。したがって、おそらくダークとライトの両方のテーマに対して、選択した状態の 9パッチのローカルコピーを作成する必要はありません(両方を処理し、両方をHoloテーマと同じように見せると仮定します)。ローカルコピーを1つ作成して、それを使用するだけです両方のテーマのセレクタードローアブル。
次に、ダウンロードした9パッチを必要に応じて編集する必要があります(つまり、青色を赤色に変更します)。ドロー9パッチツールを使用してファイルを確認し、編集後に正しく定義されているかどうかを確認できます。
1 ピクセルの鉛筆ツール(かなり簡単)でGIMPを使用してファイルを編集しましたが、おそらく独自のツールを使用します。以下は、フォーカスされた状態用にカスタマイズした9パッチです。
注:簡単にするために、私はmdpi密度の画像のみを使用しました。どのデバイスでも最高の結果が得られるようにするには、複数の画面密度の9パッチを作成する必要があります。Holoの イメージはSearchView
、mdpi、hdpi、およびxhdpiドローアブルにあります。
ここで、ビューステートに基づいて適切な画像が表示されるように、ドローアブルセレクターを作成する必要があります。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コンストラクタの一つが膨張、レイアウトという行を見つけることができます。
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を介してアクセス可能であるならば素晴らしいことですが、残念ながらそうではありません。比較のために、他の参照テーマの両方に存在している属性themes.xmlとR.attrようtextAppearanceまたはselectableItemBackgroundを。XMLでアプリケーション全体のテーマを定義するときsearchViewTextField
にR.attr
(およびR.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つで青い線を認識しているため、ローカルコピーを作成し、必要に応じて色を変更します。