【Android開発】AppCompatのSearchViewのテキストカラーやアイコンを変更する

AppCompatのSearchViewのアイコンやテキストカラーを変更しようと思い、style.xmlで変更出来るだろうと考えていたら、どうやらそう簡単にはいかないらしく、変更する方法を見つけるのに意外と手間がかかったので、メモとして書いておきます。

今回の開発環境

  • Mac OS X 10.9.4
  • Android Studio Beta 0.8.6

前準備

まず、SearchViewを追加したいmenuリソースに以下のようにメニューアイテムを追加します。
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      tools:context=".MainActivity">
    <item
        android:id="@+id/search_view"
        app:actionViewClass="android.support.v7.widget.SearchView"
        android:icon="@drawable/ic_action_search"
        android:showAsAction="always"
        android:title="Search"
        app:showAsAction="always" />
</menu>
次に、Activityの onCreateOptionsMenu() で SearchView を取得しておきます。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    SearchView searchView =
            (SearchView) MenuItemCompat.getActionView(
                    menu.findItem(R.id.search_view)
            );
    return true;
}
また、取得したSearchViewから SearchAutoComplete を取得しておきます。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    /* 省略 */
    SearchView.SearchAutoComplete searchAutoComplete =
            (SearchView.SearchAutoComplete) searchView
                .findViewById(
                    android.support.v7.appcompat.R.id.search_src_text
                );
    /* 省略 */
}
これで準備完了です。

ActionBarのSearchViewのアイコンを変更する

ActionBarのSearchViewのアイコンを変更するには、SearchViewからアイコンを表示しているImageViewを取得し、画像を差し替えることで変更できます。
具体的には以下のようにします。
ImageView searchIcon = (ImageView)
        searchView.findViewById(
                android.support.v7.appcompat.R.id.search_button
        );
searchIcon.setImageResource(R.drawable.ic_action_search);

SearchAutoComplete内のSearchViewアイコンを変更する

SearchViewのSearchAutoComplete内のアイコンを変更するには、以下のようにSpannableStringBuilderを使ってHintTextと一緒にアイコンを変更します。
SpannableStringBuilder ssb = new SpannableStringBuilder("   ");
// ヒントテキスト
ssb.append("Enter the keyword");
// ヒントアイコン
Drawable searchHintIcon =
        getResources().getDrawable(R.drawable.ic_action_search);
int textSize = (int) (searchAutoComplete.getTextSize() * 1.25);
searchHintIcon.setBounds(0, 0, textSize, textSize);
ssb.setSpan(
        new ImageSpan(searchHintIcon),
        1,
        2,
        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
searchAutoComplete.setHint(ssb);

SearchViewのテキストカラーを変更する

既にSearchViewからSearchAutoCompleteを取得しているので、これのsetTextColor()メソッドを使うことで、テキストカラーを変更することができます。
searchAutoComplete.setTextColor(Color.rgb(0x56, 0x77, 0xfc));

SearchViewのヒントテキストのカラーを変更する

これも、SearchAutoCompleteのsetHintTextColor()メソッドを使うことで、テキストカラーを変更することができます。
searchAutoComplete.setHintTextColor(Color.rgb(0x91, 0xa7, 0xff));

SearchViewのテキスト削除アイコンを変更する

SearchViewに文字を入力すると右側に出てくる削除アイコンを変更するには、ActionBarのアイコンと同様に、SearchViewからアイコンを表示しているImageViewを取得し、画像を差し替えることで変更することができます。
ImageView removeIcon =
        (ImageView) searchView.findViewById(
                android.support.v7.appcompat.R.id.search_close_btn
        );
removeIcon.setImageResource(R.drawable.ic_action_remove);

コード全体

これらのコードをまとめると、コード全体はこのようになります。
res/menu/main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      tools:context=".MainActivity">
    <item
        android:id="@+id/search_view"
        app:actionViewClass="android.support.v7.widget.SearchView"
        android:icon="@drawable/ic_action_search"
        android:showAsAction="always"
        android:title="Search"
        app:showAsAction="always" />
</menu>
MainActivity.java
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.SearchView;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ImageSpan;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        SearchView searchView =
                (SearchView) MenuItemCompat.getActionView(
                        menu.findItem(R.id.search_view)
                );
        SearchView.SearchAutoComplete searchAutoComplete =
                (SearchView.SearchAutoComplete) searchView
                        .findViewById(
                                android.support.v7.appcompat.R.id.search_src_text
                        );
        // ActionBarの検索アイコン
        ImageView searchIcon = (ImageView)
                searchView.findViewById(
                        android.support.v7.appcompat.R.id.search_button
                );
        searchIcon.setImageResource(R.drawable.ic_action_search);

        SpannableStringBuilder ssb = new SpannableStringBuilder("   ");
        // ヒントテキスト
        ssb.append("Enter the keyword");
        // ヒントアイコン
        Drawable searchHintIcon =
                getResources().getDrawable(R.drawable.ic_action_search);
        int textSize = (int) (searchAutoComplete.getTextSize() * 1.25);
        searchHintIcon.setBounds(0, 0, textSize, textSize);
        ssb.setSpan(
                new ImageSpan(searchHintIcon),
                1,
                2,
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
        );
        searchAutoComplete.setHint(ssb);

        // テキストカラー
        searchAutoComplete.setTextColor(Color.rgb(0x56, 0x77, 0xfc));
        // ヒントテキストカラー
        searchAutoComplete.setHintTextColor(
                Color.rgb(0x91, 0xa7, 0xff)
        );
        // Remove button icon
        ImageView removeIcon =
                (ImageView) searchView.findViewById(
                        android.support.v7.appcompat.R.id.search_close_btn
                );
        removeIcon.setImageResource(R.drawable.ic_action_remove);

        return true;
    }
}

実行してみる

実際に実行してみると、このようにアイコンやテキストカラーが変更されていることが確認できます。




まとめ

あまりスマートな方法ではないですが、なんとかテキストカラーやアイコンを自分の好きなものに変更することができました。
本当はstyle.xmlで一括で変更出来ると良いのですが、残念ながら自分ではstyle.xmlから変更する方法を見つけられなかったので、「style.xmlで変更する方法、知ってるよ!」という方が居れば、コメントなどで教えていただけると助かります。
このソースコードはgithubでも公開していますので、よろしければどうぞ。
https://github.com/syarihu/SearchViewTest
では、お疲れ様でした。

参考記事




コメント

人気の投稿

[Qiita] Google Playのクローズドベータ版テストでメールアドレスを指定して公開する

[Qiita] Androidの実機でPCのlocalhostに接続したり、Webページの要素を検証する

[Qiita] AppCompatのAlertDialogのテーマカラーを変える