Выбрать главу

Figure 36-1. The Android local search pop-up

Figure 36-2. The Android global search pop-up, showing a drop-down with previous searches

Search Yourself

Over the long haul, there will be two flavors of search available via the Android search system:

• Query-style search, where the user’s search string is passed to an activity that is responsible for conducting the search and displaying the results

• Filter-style search, where the user’s search string is passed to an activity on every key press, and the activity is responsible for updating a displayed list of matches

Since the latter approach is under heavy development right now by the Android team, let’s focus on the first one.

Craft the Search Activity

The first thing you’ll want to do if you want to support query-style search in your application is to create a search activity. While it might be possible to have a single activity be both opened from the launcher and opened from a search, that might prove somewhat confusing to users. Certainly, for the purposes of learning the techniques, having a separate activity is cleaner.

The search activity can have any look you want. In fact, other than watching for queries, a search activity looks, walks, and talks like any other activity in your system.

All the search activity needs to do differently is check the intents supplied to onCreate() (via getIntent()) and onNewIntent() to see if one is a search, and, if so, to do the search and display the results.

For example, let’s look at the Search/Lorem sample application (available in the Source Code section of http://apress.com). This starts off as a clone of the list-of-lorem-ipsum-words application that we first built back when showing off the ListView container in Chapter 8, then with XML resources in Chapter 19. Now we update it to support searching the list of words for ones containing the search string.

The main activity and the search activity share a common layout: a ListView plus a TextView showing the selected entry:

<?xml version="1.0" encoding="utf-8"?>

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

 android:orientation="vertical"

 android:layout_width="fill_parent"

 android:layout_height="fill_parent" >

 <TextView

  android:id="@+id/selection"

  android:layout_width="fill_parent"

  android:layout_height="wrap_content"

 />

 <ListView

  android:id="@android:id/list"

  android:layout_width="fill_parent"

  android:layout_height="fill_parent"

  android:drawSelectorOnTop="false"

 />

</LinearLayout>

In terms of Java code, most of the guts of the activities are poured into an abstract LoremBase class:

abstract public class LoremBase extends ListActivity {

 abstract ListAdapter makeMeAnAdapter(Intent intent);

 private static final int LOCAL_SEARCH_ID = Menu.FIRST+1;

 private static final int GLOBAL_SEARCH_ID = Menu.FIRST+2;

 private static final int CLOSE_ID = Menu.FIRST+3;

 TextView selection;

 ArrayList<String> items = new ArrayList<String>();

 @Override

 public void onCreate(Bundle icicle) {

  super.onCreate(icicle);

  setContentView(R.layout.main);

  selection = (TextView)findViewById(R.id.selection);

  try {

   XmlPullParser xpp = getResources().getXml(R.xml.words);

   while (xpp.getEventType()!=XmlPullParser.END_DOCUMENT) {

    if (xpp.getEventType()==XmlPullParser.START_TAG) {

     if (xpp.getName().equals("word")) {

      items.add(xpp.getAttributeValue(0));

     }

    }

    xpp.next();

   }

  } catch (Throwable t) {

   Toast

   .makeText(this, "Request failed: " + t.toString(), 4000).show();

  }

  setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);

  onNewIntent(getIntent());

 }

 @Override

 public void onNewIntent(Intent intent) {

  ListAdapter adapter = makeMeAnAdapter(intent);

  if (adapter==null) {

   finish();

  } else {

   setListAdapter(adapter);

  }

 }

 public void onListItemClick(ListView parent, View v, int position,

  long id) {

  selection.setText(items.get(position).toString());

 }

 @Override

 public boolean onCreateOptionsMenu(Menu menu) {

  menu.add(Menu.NONE, LOCAL_SEARCH_ID, Menu.NONE, "Local Search")

   .setIcon(android.R.drawable.ic_search_category_default);

  menu.add(Menu.NONE, GLOBAL_SEARCH_ID, Menu.NONE, "Global Search")

   .setIcon(R.drawable.search).setAlphabeticShortcut(SearchManager.MENU_KEY);

  menu.add(Menu.NONE, CLOSE_ID, Menu.NONE, "Close")

   .setIcon(R.drawable.eject).setAlphabeticShortcut('c');

  return(super.onCreateOptionsMenu(menu));