One of the most useful UI widgets to get introduced into the
Android framework was the
search view widget that showed up in Honeycomb. The search view widget provides
an easy way to incorporate a standard search into the header of any activity.
Unfortunately, because it was intended to be a universal search across the
entire platform, there is no baked-in way to style the widget. That means on
most modern devices, the user will see white text and a blue line, which is
fine — until it isn’t.

By that I mean, despite good intentions, sometimes that blue
will just clash, or the white text won’t be visible. You could argue that one
simply needs to change the background color of the action bar to something that
works better with the blue and white scheme, but I feel I shouldn’t have to
compromise my app’s color palette because it clashes with something
Google chose — especially since as we’ve seen in the past the very next
version of Android may yet again push us toward a new color scheme. And,
various hardware vendors like to override these color schemes with their own
take as well.

Recently I ran across this exact issue while creating an app
for a client. This client has a well-known established brand and really wanted
an action bar that communicated that brand across the entirety of the app. This
meant bright red and white text that when combined with the neon blue of the
default search view was anything but pleasing to the eye.

It took a bit of digging into the Android SDK, but through
the magic of open source I managed to cobble something together that allowed me
to style the text color and background of the search view. The tutorial that follows will show you how
to do the same. You can follow along or download and import the entire project into Eclipse. (This tutorial doesn’t cover the
implementation of a search view or for that matter even wire it up. If you
aren’t familiar with the search view, I recommend reading Google’s official documentation before proceeding.)

1. Create a new Android project in Eclipse. Target Android
3.1 or better.

2. In the /res/layout folder, we can stick with the
generated activity_main.xml definition.

activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />

</RelativeLayout>

3. In the /res/menu folder, modify main.xml to include a
search view widget.

<menu xmlns:android="http://schemas.android.com/apk/res/android" >

<item
android:id="@+id/search"
android:actionViewClass="android.widget.SearchView"
android:showAsAction="always"
android:title="Search"/>

</menu>

4. In the /src/MainActivity.java file, we will need to
modify the on create options menu to reach into the Android default layout, pull
out the search plate, and then apply the customization. The null check is
critical here since we never want the app to blow up because we couldn’t add a
custom style.

MainActivity.java
package com.authorwjf.customsearchbar;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Color;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.SearchView;
import android.widget.TextView;

public class MainActivity extends Activity {

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

@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
MenuItem menuItem = menu.findItem(R.id.search);
SearchView searchView = (SearchView) menuItem.getActionView();
searchView.setQueryHint("Type something…");
int searchPlateId = searchView.getContext().getResources().getIdentifier("android:id/search_plate", null, null);
View searchPlate = searchView.findViewById(searchPlateId);
if (searchPlate!=null) {
searchPlate.setBackgroundColor(Color.DKGRAY);
int searchTextId = searchPlate.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
TextView searchText = (TextView) searchPlate.findViewById(searchTextId);
if (searchText!=null) {
searchText.setTextColor(Color.WHITE);
searchText.setHintTextColor(Color.WHITE);
}
}
return true;
}

}

The app is ready to compile and load. Below I have samples
of the standard search (Figure A) and the custom search (Figure B).

Figure A

 

Figure B

Note: There is no guarantee this hack will work across all
OEM devices or even future versions of Android. To account for this, I took
care to fall back to the default blue if anything goes wrong along the way.
I’ve tried it on half a dozen devices, and it has performed as expected. But,
if you step over, on, or around the published SDK, you should have a good
reason and be prepared to degrade gracefully.

More Android development tips