Beginning in Android 3.0, using the SearchView widget as an item in the action bar is the preferred way to provide a search in your app. Like with all items in the action bar, you can define the SearchView to show at all times, only when there is room, or as a collapsible action, that displays the SearchView as an icon initially, then takes up the entire action bar as a search field when the user clicks the icon.
In today's article, we will create a search view. You will be able to see this SearchView as the Action bar in your emulator.
Step 1
First, download a search icon for your search bar and name it as "search". Copy this image to the clipboard. "res" -> "New" -> "Android resource directory". Name the directory as "drawable" and choose the type as "drawable". Paste the image in this directory.
Create yet another directory and name it as "raw" and choose its type as "raw". Paste that ".txt" file in this folder in which you want to perform the search. I am using a file called "definations.txt".
Step 2
To create a menu resource file: "res" -> "Menu" -> "Menu resource file". Name this file as "options_menu" and add the following code to it:
- <menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/search"
- android:title="Search"
- android:icon="@drawable/search"
- android:showAsAction="collapseActionView|ifRoom"
- android:actionViewClass="android.widget.SearchView"/>
-
- </menu>
Setting "showAsAction" to "collapseActionView" as in the preceding ensures collapsing and expanding the action bar is possible as and when required.
Step 3
Creating a searchable Configuration:
Right-click on "res" -> "New" -> "Package". Name this package as "xml". Right-click on this directory then select "New" -> "xml resource file". Name this file as "searchable" and add the following code to it:
- <searchable xmlns:android="http://schemas.android.com/apk/res/android"
- android:label="@string/search"
- android:hint="@string/enter" />
The hint will appear in the Search space.
Step 4
Add the following code to "activity_main":
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/hello_world"
- android:id="@+id/txt"/>
Step 5
"strings.xml" is used is:
- <string name="app_name" >
- SearchViews
- </string>
- <string name="action_settings" >
- Settings
- </string>
- <string name="hello_world" >
- Hello world!
- </string>
- <string name="enter" >
- Enter....
- </string>
- <string name="search" >
- Search
- </string>
Step 6
Open "MainActivity" Java file and add the following code to it:
- package com.searchviews;
-
- import android.app.SearchManager;
- import android.content.Context;
- import android.content.Intent;
- import android.os.Build;
- import android.os.Bundle;
- import android.app.Activity;
- import android.view.Menu;
- import android.view.MenuInflater;
- import android.view.MenuItem;
- import android.widget.SearchView;
- import android.widget.TextView;
-
- public class MainActivity extends Activity {
- Menu m;
- final Context context=this;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- DatabaseTable db=new DatabaseTable(this);
- }
-
-
- @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()));
-
- }
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
-
- switch (item.getItemId()) {
- case R.id.search:
- onSearchRequested();
-
- return true;
- default:
- return false;
- }
- }
- }
In the code above, SearchView will create the search view. "onSearchRequest()" is called when the user signals the desire to start a search.The SearchView starts an activity with the "ACTION_SEARCH" intent when a user submits a query.
Step 7
Now we will create a database from which we will perform the search. The "definations.txt" used by me contains a word and it's definition. I will be creating a virtual table having two columns, one for the word and the other for its definition.
Right-click on the same package then select "New" -> "Java class". Name this file as "DatabaseTable" and add the following code to it:
- package com.searchviews;
-
- import android.content.ContentValues;
- import android.content.Context;
- import android.content.res.Resources;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteOpenHelper;
- import android.database.sqlite.SQLiteQueryBuilder;
- import android.text.TextUtils;
- import android.util.Log;
-
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
-
- public class DatabaseTable {
-
- private final DatabaseOpenHelper mDatabaseOpenHelper;
- private static final String TAG = "DictionaryDatabase";
- 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;
-
-
- public DatabaseTable(Context context) {
- mDatabaseOpenHelper = new DatabaseOpenHelper(context);
- }
-
- 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;
- }
-
- 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 + ")";
- private SQLiteOpenHelper mDatabaseOpenHelper;
-
- 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);
- loadDictionary();
- }
-
- @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);
-
- }
-
- 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.definations);
- 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);
- }
-
-
- }
- }
"getWordMatches" functions perform the major matching task.
Step 8
Now we will create our search activity. Create a Java file and name it "SearchResultsActivity". Add the following code to it:
- package com.searchviews;
-
- import android.*;
- import android.R;
- import android.app.Activity;
- import android.app.SearchManager;
- import android.content.Context;
- import android.content.Intent;
- import android.database.Cursor;
- import android.os.Bundle;
- import android.view.View;
- import android.widget.AdapterView;
- import android.widget.ArrayAdapter;
- import android.widget.ListView;
- import android.widget.TextView;
-
- public class SearchResultsActivity extends Activity {
- DatabaseTable db = new DatabaseTable(this);
- final Context context=this;
- ListView list;
- TextView v;
- String res;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.simple_list_item_1);
- v=(TextView)findViewById(R.id.text1);
-
- handleIntent(getIntent());
- v.setText(res);
-
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- handleIntent(getIntent());
- }
-
- private void handleIntent(Intent intent) {
- if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
- String query = intent.getStringExtra(SearchManager.QUERY);
- Cursor c = db.getWordMatches(query, null);
- c.moveToFirst();
- res=c.getString(1);
-
-
- }
- }
- }
The "onCreate" function calls the "handleIntent" function. "handleIntent" performs the search and returns the result to a Cursor. Back in "onCreate" I retrieved and printed the result of searching. The output, in this case, is the definition of the word entered.
Step 9
Now the most important part!!
Open "AndroidManifest" and make the following changes to it:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.searchviews"
- android:versionCode="1"
- android:versionName="1.0" >
-
- <uses-sdk
- android:minSdkVersion="11"
- android:targetSdkVersion="15" />
-
- <application
- android:allowBackup="true"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:theme="@style/AppTheme" >
- <activity
- android:name="com.searchviews.MainActivity"
- android:label="@string/app_name" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- <meta-data android:name="android.app.default_searchable"
-
- android:value=".SearchResultsActivity"/>
- </activity>
-
- <activity
- android:name="com.searchviews.SearchResultsActivity"
- android:label="Search Activity">
- <intent-filter>
- <action android:name="android.intent.action.SEARCH" />
- </intent-filter>
- <meta-data
- android:name="android.app.searchable"
- android:resource="@xml/searchable" />
- </activity>
-
- </application>
-
- </manifest>
Note that if do not make your main activity (MainActivity) and the search activity (SearchResultsActivity) searchable, your code will not work.
The output snapshots:
The red mark in the preceding figure shows the search icon. Clicking on it gives:
Enter the word:
Search Result:
Thank you... Enjoy coding :)