Reader Level:
ARTICLE

Creating Search View in Android Studio

Posted by Chhavi Goel Articles | Android Programming June 14, 2013
This tutorial creates a simple search view. Searching will be performed in a Database. Database takes its values from a text file
  • 0
  • 0
  • 9529
Download Files:
 

Introduction

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) {

        //return super.onOptionsItemSelected(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 performs 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:

im1.png

The red mark in the preceding figure shows the search icon. Clicking on it gives:

im2new.jpg

Enter the word:

im3new.jpg

Search Result:

im4new.jpg

 Thank you.... Enjoy coding :)

COMMENT USING