Software Development

Pro tip: Customize the Android search view widget

This easy hack allows you to customize the text color and background of Android's search view widget.

androidlogo2.jpg
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

Androidstandardsearch112613.png
 




Figure B

Androidcustomsearch112613.png






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

 

About

William J Francis began programming computers at age eleven. Specializing in embedded and mobile platforms, he has more than 20 years of professional software engineering under his belt, including a four year stint in the US Army's Military Intellige...

0 comments

Editor's Picks