Change TextColor in SearchView using Android Toolbar

David_E picture David_E · Nov 26, 2014 · Viewed 17.3k times · Source

I have the following problem. I've setup my Actionbar to use a Toolbar instead using the API 21 with the appcompat-v7:21. The textColorPrimary style tag is configured to use the color @android:color/white, so all the titles in the new Android Toolbar will have a white text color (so far so good).

Now I´ve added a SearchView, and setup a custom background to it like this:

<style name="AppTheme.Base" parent="Theme.AppCompat.Light">
    <item name="colorPrimary">@color/action_bar_background</item>
    <item name="colorPrimaryDark">@color/status_background</item>
    <item name="android:windowNoTitle">true</item>
    <item name="windowActionBar">false</item>
    <item name="android:textColorPrimary">@android:color/white</item>
    <item name="searchViewStyle">@style/SearchViewStyle</item>
</style>

<style name="SearchViewStyle" parent="Widget.AppCompat.SearchView">
    <item name="queryBackground">@drawable/search_background</item>
    <item name="searchIcon">@drawable/icon_search</item>
</style>

The drawable @drawable/search_background is a plain white rectangle. So guess what? As the title text color in the Toolbar is white, now the text color in the SearchView is white as well, and as the SearchView background is a white rectangle, the user can't see what he's typing.

My Question is: How can I have different text colors for the Android Toolbar Title and the SearchView text?

Answer

David_E picture David_E · Nov 26, 2014

After some research I found a secure way to do it.

Digging up in the SearchView styles, I found the layout that is used to display the SearchView. Inside that layout there's a TextView (the actual field where you type in the SearchView)

<TextView
        android:id="@+id/search_badge"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:layout_marginBottom="2dip"
        android:drawablePadding="0dip"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="?android:attr/textColorPrimary"
        android:visibility="gone" />

Notice the field android:textColor="?android:attr/textColorPrimary". This causes the problem I originally had, the text color in the SearchView is the same as the one defined for the Title text color in the Android Toolbar.

Now there're are several solutions that might work here, but I think that most of those solutions have the same problem. They all rely in the id of the TextView in order to access the view and change the text color, as described here

Personally I think that hardcoding the id of the TextView inside the code is highly risky, because we don't know if tomorrow Google decides to use another id value for this view, in that case, our code will be broken.

For that reason I've created a recursive method that obtains the TextView object in the SearchView, and changes the color to whatever we want.

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    menu.clear();
    inflater.inflate(R.menu.search, menu);
    SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();

    searchView.setOnQueryTextListener(new SearchTextListener());
    changeSearchViewTextColor(searchView);
}


private void changeSearchViewTextColor(View view) {
    if (view != null) {
        if (view instanceof TextView) {
            ((TextView) view).setTextColor(Color.BLACK);
            return;
        } else if (view instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) view;
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                changeSearchViewTextColor(viewGroup.getChildAt(i));
            }
        }
    }
}

I've tested this code using API 21 with the Toolbar, having the Toolbar Title text color set to white, and setting up the SearchView text color to black and it works perfectly. Also, as we're accessing the TextView object directly, we can change the hint, drawable, paddings, and everything related to the TextView.