am b285125d: Merge "docs: android u search class" into ics-mr1
* commit 'b285125d4bad1c76e95cd24956711deb9908c4a8': docs: android u search class
This commit is contained in:
@@ -98,6 +98,26 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li class="toggle-list">
|
||||||
|
<div><a href="<?cs var:toroot ?>training/search/index.html">
|
||||||
|
<span class="en">Adding Search Functionality</span>
|
||||||
|
</a></div>
|
||||||
|
<ul>
|
||||||
|
<li><a href="<?cs var:toroot ?>training/search/setup.html">
|
||||||
|
<span class="en">Setting up the Search Interface</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="<?cs var:toroot ?>training/search/search.html">
|
||||||
|
<span class="en">Storing and Searching for Data</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="<?cs var:toroot ?>training/search/backward-compat.html">
|
||||||
|
<span class="en">Remaining Backward Compatible</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li class="toggle-list">
|
<li class="toggle-list">
|
||||||
<div><a href="<?cs var:toroot ?>training/id-auth/index.html">
|
<div><a href="<?cs var:toroot ?>training/id-auth/index.html">
|
||||||
<span class="en">Remembering Users</span>
|
<span class="en">Remembering Users</span>
|
||||||
|
|||||||
87
docs/html/training/search/backward-compat.jd
Normal file
87
docs/html/training/search/backward-compat.jd
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
page.title=Remaining Backward Compatible
|
||||||
|
trainingnavtop=true
|
||||||
|
previous.title=Storing and Searching for Data
|
||||||
|
previous.link=search.html
|
||||||
|
|
||||||
|
@jd:body
|
||||||
|
|
||||||
|
<div id="tb-wrapper">
|
||||||
|
<div id="tb">
|
||||||
|
<h2>This lesson teaches you to</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="{@docRoot}training/search/backward-compat.html#set-sdk">Set Minimum and Target
|
||||||
|
SDK Values</a></li>
|
||||||
|
|
||||||
|
<li><a href="{@docRoot}training/search/backward-compat.html#provide-sd">Provide the Search
|
||||||
|
Dialog for Older Devices</a></li>
|
||||||
|
|
||||||
|
<li><a href="{@docRoot}training/search/backward-compat.html#check-ver">Check the Android Build
|
||||||
|
Version at Runtime</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>The {@link android.widget.SearchView} and action bar are only available on Android 3.0 and
|
||||||
|
later. To support older platforms, you can fall back to the search dialog. The search dialog is a
|
||||||
|
system provided UI that overlays on top of your application when invoked.</p>
|
||||||
|
|
||||||
|
<h2 id="set-sdk">Set Minimum and Target API levels</h2>
|
||||||
|
|
||||||
|
<p>To setup the search dialog, first declare in your manifest that you want to support older
|
||||||
|
devices, but want to target Android 3.0 or later versions. When you do this, your application
|
||||||
|
automatically uses the action bar on Android 3.0 or later and uses the traditional menu system on
|
||||||
|
older devices:</p>
|
||||||
|
<pre>
|
||||||
|
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="15" />
|
||||||
|
|
||||||
|
<application>
|
||||||
|
...
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2 id="provide-sd">Provide the Search Dialog for Older Devices</h2>
|
||||||
|
|
||||||
|
<p>To invoke the search dialog on older devices, call {@link
|
||||||
|
android.app.Activity#onSearchRequested onSearchRequested()} whenever a user selects the search
|
||||||
|
menu item from the options menu. Because Android 3.0 and higher devices show the
|
||||||
|
{@link android.widget.SearchView} in the action bar (as demonstrated in the first lesson), only versions
|
||||||
|
older than 3.0 call {@link android.app.Activity#onOptionsItemSelected onOptionsItemSelected()} when the
|
||||||
|
user selects the search menu item.
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case R.id.search:
|
||||||
|
onSearchRequested();
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2 id="check-ver">Check the Android Build Version at Runtime</h2>
|
||||||
|
|
||||||
|
<p>At runtime, check the device version to make sure an unsupported use of {@link
|
||||||
|
android.widget.SearchView} does not occur on older devices. In our example code, this happens in
|
||||||
|
the {@link android.app.Activity#onCreateOptionsMenu onCreateOptionsMenu()} method:</p>
|
||||||
|
<pre>
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
|
||||||
|
MenuInflater inflater = getMenuInflater();
|
||||||
|
inflater.inflate(R.menu.options_menu, menu);
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||||
|
SearchManager searchManager =
|
||||||
|
(SearchManager) getSystemService(Context.SEARCH_SERVICE);
|
||||||
|
SearchView searchView =
|
||||||
|
(SearchView) menu.findItem(R.id.search).getActionView();
|
||||||
|
searchView.setSearchableInfo(
|
||||||
|
searchManager.getSearchableInfo(getComponentName()));
|
||||||
|
searchView.setIconifiedByDefault(false);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
53
docs/html/training/search/index.jd
Normal file
53
docs/html/training/search/index.jd
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
page.title=Adding Search Functionality
|
||||||
|
trainingnavtop=true
|
||||||
|
startpage=true
|
||||||
|
next.title=Setting Up the Search Interface
|
||||||
|
next.link=setup.html
|
||||||
|
|
||||||
|
@jd:body
|
||||||
|
|
||||||
|
<div id="tb-wrapper">
|
||||||
|
<div id="tb">
|
||||||
|
<h2>Dependencies and prerequisites</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Android 3.0 or later (with some support for Android 2.1)</li>
|
||||||
|
|
||||||
|
<li>Experience building an Android <a href="{@docRoot}guide/topics/ui/index.html">User
|
||||||
|
Interface</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>You should also read</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="{@docRoot}guide/topics/search/index.html">Search</a></li>
|
||||||
|
|
||||||
|
<li><a href="{@docRoot}resources/samples/SearchableDictionary/index.html">Searchable
|
||||||
|
Dictionary Sample App</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>Android's built-in search features offer apps an easy way to provide a
|
||||||
|
consistent search experience for all users. There are two ways to implement search in your app
|
||||||
|
depending on the version of Android that is running on the device. This class covers how to add
|
||||||
|
search with {@link android.widget.SearchView}, which was introduced in Android 3.0, while
|
||||||
|
maintaining backward compatibility with older versions of Android by using the default search
|
||||||
|
dialog provided by the system.</p>
|
||||||
|
|
||||||
|
<h2>Lessons</h2>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><b><a href="setup.html">Setting Up the Search Interface</a></b></dt>
|
||||||
|
|
||||||
|
<dd>Learn how to add a search interface to your app and how to configure an activity to handle
|
||||||
|
search queries.</dd>
|
||||||
|
|
||||||
|
<dt><b><a href="search.html">Storing and Searching for Data</a></b></dt>
|
||||||
|
|
||||||
|
<dd>Learn a simple way to store and search for data in a SQLite virtual database table.</dd>
|
||||||
|
|
||||||
|
<dt><b><a href="backward-compat.html">Remaining Backward Compatible</a></b></dt>
|
||||||
|
|
||||||
|
<dd>Learn how to keep search features backward compatible with older devices by using.</dd>
|
||||||
|
</dl>
|
||||||
217
docs/html/training/search/search.jd
Normal file
217
docs/html/training/search/search.jd
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
page.title=Storing and Searching for Data
|
||||||
|
trainingnavtop=true
|
||||||
|
previous.title=Setting Up the Search Interface
|
||||||
|
previous.link=setup.html
|
||||||
|
next.title=Remaining Backward Compatible
|
||||||
|
next.link=backward-compat.html
|
||||||
|
|
||||||
|
@jd:body
|
||||||
|
|
||||||
|
<div id="tb-wrapper">
|
||||||
|
<div id="tb">
|
||||||
|
<h2>This lesson teaches you to</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="{@docRoot}training/search/search.html#create">Create the Virtual
|
||||||
|
Table</a></li>
|
||||||
|
|
||||||
|
<li><a href="{@docRoot}training/search/search.html#populate">Populate the Virtual
|
||||||
|
Table</a></li>
|
||||||
|
|
||||||
|
<li><a href="{@docRoot}training/search/search.html#search">Search for the Query</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>There are many ways to store your data, such as in an online database, in a local SQLite
|
||||||
|
database, or even in a text file. It is up to you to decide what is the best solution for your
|
||||||
|
application. This lesson shows you how to create a SQLite virtual table that can provide robust
|
||||||
|
full-text searching. The table is populated with data from a text file that contains a word and
|
||||||
|
definition pair on each line in the file.</p>
|
||||||
|
|
||||||
|
<h2 id="create">Create the Virtual Table</h2>
|
||||||
|
|
||||||
|
<p>A virtual table behaves similarly to a SQLite table, but reads and writes to an object in
|
||||||
|
memory via callbacks, instead of to a database file. To create a virtual table, create a class
|
||||||
|
for the table:</p>
|
||||||
|
<pre>
|
||||||
|
public class DatabaseTable {
|
||||||
|
private final DatabaseOpenHelper mDatabaseOpenHelper;
|
||||||
|
|
||||||
|
public DatabaseTable(Context context) {
|
||||||
|
mDatabaseOpenHelper = new DatabaseOpenHelper(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>Create an inner class in <code>DatabaseTable</code> that extends {@link
|
||||||
|
android.database.sqlite.SQLiteOpenHelper}. The {@link android.database.sqlite.SQLiteOpenHelper} class
|
||||||
|
defines abstract methods that you must override so that your database table can be created and
|
||||||
|
upgraded when necessary. For example, here is some code that declares a database table that will
|
||||||
|
contain words for a dictionary app:</p>
|
||||||
|
<pre>
|
||||||
|
public class DatabaseTable {
|
||||||
|
|
||||||
|
private static final String TAG = "DictionaryDatabase";
|
||||||
|
|
||||||
|
//The columns we'll include in the dictionary table
|
||||||
|
public static final String COL_WORD = "WORD";
|
||||||
|
public static final String COL_DEFINITION = "DEFINITION";
|
||||||
|
|
||||||
|
private static final String DATABASE_NAME = "DICTIONARY";
|
||||||
|
private static final String FTS_VIRTUAL_TABLE = "FTS";
|
||||||
|
private static final int DATABASE_VERSION = 1;
|
||||||
|
|
||||||
|
private final DatabaseOpenHelper mDatabaseOpenHelper;
|
||||||
|
|
||||||
|
public DatabaseTable(Context context) {
|
||||||
|
mDatabaseOpenHelper = new DatabaseOpenHelper(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DatabaseOpenHelper extends SQLiteOpenHelper {
|
||||||
|
|
||||||
|
private final Context mHelperContext;
|
||||||
|
private SQLiteDatabase mDatabase;
|
||||||
|
|
||||||
|
private static final String FTS_TABLE_CREATE =
|
||||||
|
"CREATE VIRTUAL TABLE " + FTS_VIRTUAL_TABLE +
|
||||||
|
" USING fts3 (" +
|
||||||
|
COL_WORD + ", " +
|
||||||
|
COL_DEFINITION + ")";
|
||||||
|
|
||||||
|
DatabaseOpenHelper(Context context) {
|
||||||
|
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
|
mHelperContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(SQLiteDatabase db) {
|
||||||
|
mDatabase = db;
|
||||||
|
mDatabase.execSQL(FTS_TABLE_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
|
||||||
|
+ newVersion + ", which will destroy all old data");
|
||||||
|
db.execSQL("DROP TABLE IF EXISTS " + FTS_VIRTUAL_TABLE);
|
||||||
|
onCreate(db);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2 id="populate">Populate the Virtual Table</h2>
|
||||||
|
|
||||||
|
<p>The table now needs data to store. The following code shows you how to read a text file
|
||||||
|
(located in <code>res/raw/definitions.txt</code>) that contains words and their definitions, how
|
||||||
|
to parse that file, and how to insert each line of that file as a row in the virtual table. This
|
||||||
|
is all done in another thread to prevent the UI from locking. Add the following code to your
|
||||||
|
<code>DatabaseOpenHelper</code> inner class.</p>
|
||||||
|
|
||||||
|
<p class="note"><strong>Tip:</strong> You also might want to set up a callback to notify your UI
|
||||||
|
activity of this thread's completion.</p>
|
||||||
|
<pre>
|
||||||
|
private void loadDictionary() {
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
loadWords();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadWords() throws IOException {
|
||||||
|
final Resources resources = mHelperContext.getResources();
|
||||||
|
InputStream inputStream = resources.openRawResource(R.raw.definitions);
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||||
|
|
||||||
|
try {
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
String[] strings = TextUtils.split(line, "-");
|
||||||
|
if (strings.length < 2) continue;
|
||||||
|
long id = addWord(strings[0].trim(), strings[1].trim());
|
||||||
|
if (id < 0) {
|
||||||
|
Log.e(TAG, "unable to add word: " + strings[0].trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long addWord(String word, String definition) {
|
||||||
|
ContentValues initialValues = new ContentValues();
|
||||||
|
initialValues.put(COL_WORD, word);
|
||||||
|
initialValues.put(COL_DEFINITION, definition);
|
||||||
|
|
||||||
|
return mDatabase.insert(FTS_VIRTUAL_TABLE, null, initialValues);
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>Call the <code>loadDictionary()</code> method wherever appropriate to populate the table. A
|
||||||
|
good place would be in the {@link android.database.sqlite.SQLiteOpenHelper#onCreate onCreate()}
|
||||||
|
method of the <code>DatabaseOpenHelper</code> class, right after you create the table:</p>
|
||||||
|
<pre>
|
||||||
|
@Override
|
||||||
|
public void onCreate(SQLiteDatabase db) {
|
||||||
|
mDatabase = db;
|
||||||
|
mDatabase.execSQL(FTS_TABLE_CREATE);
|
||||||
|
loadDictionary();
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2 id="search">Search for the Query</h2>
|
||||||
|
|
||||||
|
<p>When you have the virtual table created and populated, use the query supplied by your {@link
|
||||||
|
android.widget.SearchView} to search the data. Add the following methods to the
|
||||||
|
<code>DatabaseTable</code> class to build a SQL statement that searches for the query:</p>
|
||||||
|
<pre>
|
||||||
|
public Cursor getWordMatches(String query, String[] columns) {
|
||||||
|
String selection = COL_WORD + " MATCH ?";
|
||||||
|
String[] selectionArgs = new String[] {query+"*"};
|
||||||
|
|
||||||
|
return query(selection, selectionArgs, columns);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Cursor query(String selection, String[] selectionArgs, String[] columns) {
|
||||||
|
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
|
||||||
|
builder.setTables(FTS_VIRTUAL_TABLE);
|
||||||
|
|
||||||
|
Cursor cursor = builder.query(mDatabaseOpenHelper.getReadableDatabase(),
|
||||||
|
columns, selection, selectionArgs, null, null, null);
|
||||||
|
|
||||||
|
if (cursor == null) {
|
||||||
|
return null;
|
||||||
|
} else if (!cursor.moveToFirst()) {
|
||||||
|
cursor.close();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return cursor;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>Search for a query by calling <code>getWordMatches()</code>. Any matching results are returned
|
||||||
|
in a {@link android.database.Cursor} that you can iterate through or use to build a {@link android.widget.ListView}.
|
||||||
|
This example calls <code>getWordMatches()</code> in the <code>handleIntent()</code> method of the searchable
|
||||||
|
activity. Remember that the searchable activity receives the query inside of the {@link
|
||||||
|
android.content.Intent#ACTION_SEARCH} intent as an extra, because of the intent filter that you
|
||||||
|
previously created:</p>
|
||||||
|
<pre>
|
||||||
|
DatabaseTable db = new DatabaseTable(this);
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
private void handleIntent(Intent intent) {
|
||||||
|
|
||||||
|
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
|
||||||
|
String query = intent.getStringExtra(SearchManager.QUERY);
|
||||||
|
Cursor c = db.getWordMatches(query, null);
|
||||||
|
//process Cursor and display results
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
197
docs/html/training/search/setup.jd
Normal file
197
docs/html/training/search/setup.jd
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
page.title=Setting Up the Search Interface
|
||||||
|
trainingnavtop=true
|
||||||
|
next.title=Storing and Searching for Data
|
||||||
|
next.link=search.html
|
||||||
|
|
||||||
|
@jd:body
|
||||||
|
|
||||||
|
<div id="tb-wrapper">
|
||||||
|
<div id="tb">
|
||||||
|
<h2>This lesson teaches you to</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="{@docRoot}training/search/setup.html#add-sv">Add the Search View to the Action
|
||||||
|
Bar</a></li>
|
||||||
|
|
||||||
|
<li><a href="{@docRoot}training/search/setup.html#create-sc">Create a Searchable
|
||||||
|
Configuration</a></li>
|
||||||
|
|
||||||
|
<li><a href="{@docRoot}training/search/setup.html#create-sa">Create a Searchable
|
||||||
|
Activity</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>You should also read:</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>Beginning in Android 3.0, using the {@link android.widget.SearchView} widget as an item in
|
||||||
|
the action bar is the preferred way to provide search in your app. Like with all items in
|
||||||
|
the action bar, you can define the {@link android.widget.SearchView} to show at all times, only
|
||||||
|
when there is room, or as a collapsible action, which displays the {@link
|
||||||
|
android.widget.SearchView} as an icon initially, then takes up the entire action bar as a search
|
||||||
|
field when the user clicks the icon.</p>
|
||||||
|
|
||||||
|
<p class="note"><strong>Note:</strong> Later in this class, you will learn how to make your
|
||||||
|
app compatible down to Android 2.1 (API level 7) for devices that do not support
|
||||||
|
{@link android.widget.SearchView}.</p>
|
||||||
|
|
||||||
|
<h2 id="add-sv">Add the Search View to the Action Bar</h2>
|
||||||
|
|
||||||
|
<p>To add a {@link android.widget.SearchView} widget to the action bar, create a file named
|
||||||
|
<code>res/menu/options_menu.xml</code> in your project and add the following code to the file.
|
||||||
|
This code defines how to create the search item, such as the icon to use and the title of the
|
||||||
|
item. The <code>collapseActionView</code> attribute allows your {@link android.widget.SearchView}
|
||||||
|
to expand to take up the whole action bar and collapse back down into a
|
||||||
|
normal action bar item when not in use. Because of the limited action bar space on handset devices,
|
||||||
|
using the <code>collapsibleActionView</code> attribute is recommended to provide a better
|
||||||
|
user experience.</p>
|
||||||
|
<pre>
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:id="@+id/search"
|
||||||
|
android:title="@string/search_title"
|
||||||
|
android:icon="@drawable/ic_search"
|
||||||
|
android:showAsAction="collapseActionView|ifRoom"
|
||||||
|
android:actionViewClass="android.widget.SearchView" />
|
||||||
|
</menu>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p class="note"><strong>Note:</strong> If you already have an existing XML file for your menu
|
||||||
|
items, you can add the <code><item></code> element to that file instead.</p>
|
||||||
|
|
||||||
|
<p>To display the {@link android.widget.SearchView} in the action bar, inflate the XML menu
|
||||||
|
resource (<code>res/menu/options_menu.xml</code>) in the {@link
|
||||||
|
android.app.Activity#onCreateOptionsMenu onCreateOptionsMenu()} method of your activity:</p>
|
||||||
|
<pre>
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
MenuInflater inflater = getMenuInflater();
|
||||||
|
inflater.inflate(R.menu.options_menu, menu);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>If you run your app now, the {@link android.widget.SearchView} appears in your app's action
|
||||||
|
bar, but it isn't functional. You now need to define <em>how</em> the {@link
|
||||||
|
android.widget.SearchView} behaves.</p>
|
||||||
|
|
||||||
|
<h2 id="create-sc">Create a Searchable Configuration</h2>
|
||||||
|
|
||||||
|
<p>A <a href="http://developer.android.com/guide/topics/search/searchable-config.html">searchable
|
||||||
|
configuration</a> defines how the {@link android.widget.SearchView} behaves and is defined in a
|
||||||
|
<code>res/xml/searchable.xml</code> file. At a minimum, a searchable configuration must contain
|
||||||
|
an <code>android:label</code> attribute that has the same value as the
|
||||||
|
<code>android:label</code> attribute of the <a href="{@docRoot}guide/topics/manifest/application-element.html"><application></a> or
|
||||||
|
<a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a> element in your Android manifest.
|
||||||
|
However, we also recommend adding an <code>android:hint</code> attribute to give the user an idea of what to enter into the search
|
||||||
|
box:</p>
|
||||||
|
<pre>
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:hint="@string/search_hint" />
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>In your application's manifest file, declare a <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">
|
||||||
|
<code><meta-data></code></a> element that points to the <code>res/xml/searchable.xml</code> file,
|
||||||
|
so that your application knows where to find it. Declare the element in an <code><activity></code>
|
||||||
|
that you want to display the {@link android.widget.SearchView} in:</p>
|
||||||
|
<pre>
|
||||||
|
<activity ... >
|
||||||
|
...
|
||||||
|
<meta-data android:name="android.app.searchable"
|
||||||
|
android:resource="@xml/searchable" />
|
||||||
|
|
||||||
|
</activity>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>In the {@link android.app.Activity#onCreateOptionsMenu onCreateOptionsMenu()} method that you
|
||||||
|
created before, associate the searchable configuration with the {@link android.widget.SearchView}
|
||||||
|
by calling {@link android.widget.SearchView#setSearchableInfo}:</p>
|
||||||
|
<pre>
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
MenuInflater inflater = getMenuInflater();
|
||||||
|
inflater.inflate(R.menu.options_menu, menu);
|
||||||
|
|
||||||
|
// Associate searchable configuration with the SearchView
|
||||||
|
SearchManager searchManager =
|
||||||
|
(SearchManager) getSystemService(Context.SEARCH_SERVICE);
|
||||||
|
SearchView searchView =
|
||||||
|
(SearchView) menu.findItem(R.id.search).getActionView();
|
||||||
|
searchView.setSearchableInfo(
|
||||||
|
searchManager.getSearchableInfo(getComponentName()));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>The call to {@link android.app.SearchManager#getSearchableInfo getSearchableInfo()} obtains a
|
||||||
|
{@link android.app.SearchableInfo} object that is created from the searchable configuration XML
|
||||||
|
file. When the searchable configuration is correctly associated with your {@link
|
||||||
|
android.widget.SearchView}, the {@link android.widget.SearchView} starts an activity with the
|
||||||
|
{@link android.content.Intent#ACTION_SEARCH} intent when a user submits a query. You now need an
|
||||||
|
activity that can filter for this intent and handle the search query.</p>
|
||||||
|
|
||||||
|
<h2 id="create-sa">Create a Searchable Activity</h2>
|
||||||
|
|
||||||
|
<p>A {@link android.widget.SearchView} tries to start an activity with the {@link
|
||||||
|
android.content.Intent#ACTION_SEARCH} when a user submits a search query. A searchable activity
|
||||||
|
filters for the {@link android.content.Intent#ACTION_SEARCH} intent and searches for the query in
|
||||||
|
some sort of data set. To create a searchable activity, declare an activity of your choice to
|
||||||
|
filter for the {@link android.content.Intent#ACTION_SEARCH} intent:</p>
|
||||||
|
<pre>
|
||||||
|
<activity android:name=".SearchResultsActivity" ... >
|
||||||
|
...
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.SEARCH" />
|
||||||
|
</intent-filter>
|
||||||
|
...
|
||||||
|
</activity>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>In your searchable activity, handle the {@link android.content.Intent#ACTION_SEARCH} intent by
|
||||||
|
checking for it in your {@link android.app.Activity#onCreate onCreate()} method.</p>
|
||||||
|
|
||||||
|
<p class="note"><strong>Note:</strong> If your searchable activity launches in single top mode
|
||||||
|
(<code>android:launchMode="singleTop"</code>), also handle the {@link
|
||||||
|
android.content.Intent#ACTION_SEARCH} intent in the {@link android.app.Activity#onNewIntent
|
||||||
|
onNewIntent()} method. In single top mode, only one instance of your activity is created and
|
||||||
|
subsequent calls to start your activity do not create a new activity on the
|
||||||
|
stack. This launch mode is useful so users can perform searches from the same activity
|
||||||
|
without creating a new activity instance every time.</p>
|
||||||
|
<pre>
|
||||||
|
public class SearchResultsActivity extends Activity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
...
|
||||||
|
handleIntent(getIntent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onNewIntent(Intent intent) {
|
||||||
|
...
|
||||||
|
handleIntent(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleIntent(Intent intent) {
|
||||||
|
|
||||||
|
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
|
||||||
|
String query = intent.getStringExtra(SearchManager.QUERY);
|
||||||
|
//use the query to search your data somehow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
...
|
||||||
|
}
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>If you run your app now, the {@link android.widget.SearchView} can accept the user's query and
|
||||||
|
start your searchable activity with the {@link android.content.Intent#ACTION_SEARCH} intent. It
|
||||||
|
is now up to you to figure out how to store and search your data given a query.</p>
|
||||||
Reference in New Issue
Block a user