Использование Android Search Dialog. Пример простого приложения
Данная статья предназначена для тех, кто уже написал свой HelloWorld для Android и знает, что такое Activity и Intent, а так же где находится манифест, и зачем нужны layout'ы. В противном случае, можно ознакомиться с этим материалом, например, на developer.android.com.
В статье описывается создание несложного приложения, которое использует механизм реализации поиска, основанный на возможностях встроенного фреймворка. После прочтения вы также сможете настроить свое приложение таким образом, чтобы оно осуществляло поиск по данным, используя стандартный Android Search Dialog.
Немного теорииAndroid Search Dialog (далее — «диалог поиска») управляется с помощью поискового фреймворка. Это означает, что разработчику не нужно задумываться над тем как его нарисовать или как отловить поисковый запрос. За вас эту работу сделает SearchManager.
- Конфигурационный xml файл (в нем содержится информация о диалоге)
- Activity, которое будет получать поисковые запросы, выполнять поиск и выводить результаты на экран
- Механизм вызова поискового диалога (так как не все устройства с Android на борту имеют на корпусе кнопку поиска)
<? 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" > </ searchable >
* This source code was highlighted with Source Code Highlighter .
Обязательным атрибутом является только android:label, причем он должен ссылаться на строку, которая является такой же, что и название приложения. Второй атрибут, android:hint используется для отображения строки в пустом диалоге. Например, это может быть «Поиск по Видео» или «Поиск контактов» и т.п. Этот атрибут указывает на то, по каким данным осуществляется поиск. Также важно знать, что элемент searchable поддерживает множество других атрибутов, подробнее можно прочесть Здесь.
Создаем ActivityМинимально, всё что нам нужно от пользовательского интерфейса Activity — это список для вывода результатов поиска и механизм вызова поискового диалога. Так и сделаем, добавив только поле для ввода текста и кнопку, чтобы мы сами могли заполнять базу. Забегая вперед, скажу, что данные будем хранить в БД SQLite.
Опишем интерфейс Activity следующим образом (файл находится в res/layout/main.xml).
<? 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" > < LinearLayout android:orientation ="horizontal" android:layout_width ="fill_parent" android:layout_height ="wrap_content" android:gravity ="top" > < EditText android:id ="@+id/text" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:hint ="@string/text" android:layout_weight ="100.0" /> < Button android:id ="@+id/add" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:text ="@string/add" /> </ LinearLayout > < ListView android:id ="@android:id/list" android:layout_width ="fill_parent" android:layout_height ="wrap_content" /> < TextView android:layout_gravity ="left" android:id ="@android:id/empty" android:layout_width ="fill_parent" android:layout_height ="fill_parent" android:text ="@string/no_records" /> </ LinearLayout >
* This source code was highlighted with Source Code Highlighter .
Выглядит следующим образом:
Также нам понадобится layout для вида элемента списка, опишем его простейшим образом (файл находится в res/layout/record.xml)
<? xml version ="1.0" encoding ="utf-8" ? > < TextView android:id ="@+id/text1" xmlns:android ="http://schemas.android.com/apk/res/android" android:layout_width ="wrap_content" android:layout_height ="wrap_content" />
* This source code was highlighted with Source Code Highlighter .
Также, не забываем про файл ресурсов, где хранятся наши строки (файл в res/values/strings.xml)
<? xml version ="1.0" encoding ="utf-8" ? > < resources > < string name ="app_name" > SearchExample </ string > < string name ="add" > Add </ string > < string name ="text" > Enter text </ string > < string name ="no_records" > There are no records in the table </ string > < string name ="search_hint" > Search the records </ string > < string name ="search" > Search </ string > </ resources >
* This source code was highlighted with Source Code Highlighter .
<? xml version ="1.0" encoding ="utf-8" ? > < manifest xmlns:android ="http://schemas.android.com/apk/res/android" package ="com.example.search" android:versionCode ="1" android:versionName ="1.0" > < application android:icon ="@drawable/icon" android:label ="@string/app_name" > < activity android:name =".Main" android:label ="@string/app_name" > < intent-filter > < action android:name ="android.intent.action.MAIN" /> < category android:name ="android.intent.category.LAUNCHER" /> </ intent-filter > < intent-filter > < action android:name ="android.intent.action.SEARCH" /> </ intent-filter > < meta-data android:name ="android.app.searchable" android:resource ="@xml/searchable" /> </ activity >
</ application > < uses-sdk android:minSdkVersion ="5" />
* This source code was highlighted with Source Code Highlighter .
Сейчас, вы уже можете проверить, все ли вы сделали правильно. Вызвать диалог на эмуляторе можно, например, нажав кнопку поиска. Ну или если вы проверяете на девайсе, то зажав «Меню». Выглядеть должно примерно так:
Выполнение поиска- Получение запроса
- Поиск данных
- вывод результатов
Так как SearchManager посылает Intent типа Search нашему Activity, то всё что нужно сделать это проверить на Intent этого типа при старте Activity. Тогда, если мы получаем нужный Intent, то можно извлекать из него экстру и выполнять поиск.
Поиск данныхТак как тип структуры хранения данных для разных приложений может различаться, то и методы для них свои. В нашем случае, проще всего выполнить запрос по таблице БД SQLite запросом LIKE. Конечно, лучше использовать FTS3, он значительно быстрее, подробнее о FTS3 можно прочесть на сайте SQLite.org. В идеале, также нужно всегда рассчитывать, что поиск может занять продолжительное время, поэтому можно создать какой-нибудь ProgressDialog, чтобы у нас не завис интерфейс, и чтобы пользователь знал, что приложение работает.
Вывод результатовВообще вывод результатов — это проблема UI, но так как мы используем ListView, то для нас проблема решается простым обновлением адаптера.
Исходный кодНаконец, привожу полный исходный код двух классов с комментариями. Первый — Main, наследник ListActivity, он используется для наполнения БД и вывода результатов. Второй класс — RecordsDbHelper, он реализует интерфейс для взаимодействия с БД. Самые важные методы — добавление записей и поиск совпадений, с помощью запроса LIKE.
Файл Main.java
import android.app.ListActivity; import android.app.SearchManager; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.SimpleCursorAdapter;
public class Main extends ListActivity
private void saveTask( String data)
private void showResults( String query) ; int [] to = new int [] < R.id.text1 >;
SimpleCursorAdapter records = new SimpleCursorAdapter( this , R.layout.record, cursor, from , to); //Обновляем адаптер setListAdapter(records); > //Создаем меню для вызова поиска (интерфейс в res/menu/main_menu.xml) public boolean onCreateOptionsMenu(Menu menu)
public boolean onOptionsItemSelected(MenuItem item) >
* This source code was highlighted with Source Code Highlighter .
Файл RecordsDbHelper.java
import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log;
public class RecordsDbHelper
* This source code was highlighted with Source Code Highlighter .