建立搜索界面

编写:Lin-H - 原文:http://developer.android.com/training/search/setup.html

从Android 3.0开始,在action bar中使用SearchView作为item,是在你的app中提供搜索的一种更好方法。像其他所有在action bar中的item一样,你可以定义SearchView在有足够空间的时候总是显示,或设置为一个折叠操作(collapsible action),一开始SearchView作为一个图标显示,当用户点击图标时再显示搜索框占据整个action bar。

Note:在本课程的后面,你会学习对那些不支持SearchView的设备,如何使你的app向下兼容至Android 2.1(API level 7)版本。

添加Search View到action bar中

为了在action bar中添加SearchView,在你的工程目录res/menu/中创建一个名为options_menu.xml的文件,再把下列代码添加到文件中。这段代码定义了如何创建search item,比如使用的图标和item的标题。collapseActionView属性允许你的SearchView占据整个action bar,在不使用的时候折叠成普通的action bar item。由于在手持设备中action bar的空间有限,建议使用collapsibleActionView属性来提供更好的用户体验。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <menu xmlns:android="http://schemas.android.com/apk/res/android">
  3. <item android:id="@+id/search"
  4. android:title="@string/search_title"
  5. android:icon="@drawable/ic_search"
  6. android:showAsAction="collapseActionView|ifRoom"
  7. android:actionViewClass="android.widget.SearchView" />
  8. </menu>

Note:如果你的menu items已经有一个XML文件,你可以只把<item>元素添加入文件。

要在action bar中显示SearchView,在你的activity中onCreateOptionsMenu())方法内填充XML菜单资源(res/menu/options_menu.xml):

  1. @Override
  2. public boolean onCreateOptionsMenu(Menu menu) {
  3. MenuInflater inflater = getMenuInflater();
  4. inflater.inflate(R.menu.options_menu, menu);
  5. return true;
  6. }

如果你立即运行你的app,SearchView就会显示在你app的action bar中,但还无法使用。你现在需要定义SearchView如何运行。

创建一个检索配置

检索配置(searchable configuration)res/xml/searchable.xml文件中定义了SearchView如何运行。检索配置中至少要包含一个android:label属性,与Android manifest中的<application><activity> android:label属性值相同。但我们还是建议添加android:hint属性来告诉用户应该在搜索框中输入什么内容:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <searchable xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:label="@string/app_name"
  4. android:hint="@string/search_hint" />

在你的应用的manifest文件中,声明一个指向res/xml/searchable.xml文件的<meta-data>元素,来告诉你的应用在哪里能找到检索配置。在你想要显示SearchView<activity>中声明<meta-data>元素:

  1. <activity ... >
  2. ...
  3. <meta-data android:name="android.app.searchable"
  4. android:resource="@xml/searchable" />
  5. </activity>

在你之前创建的onCreateOptionsMenu())方法中,调用setSearchableInfo(SearchableInfo))把SearchView和检索配置关联在一起:

  1. @Override
  2. public boolean onCreateOptionsMenu(Menu menu) {
  3. MenuInflater inflater = getMenuInflater();
  4. inflater.inflate(R.menu.options_menu, menu);
  5. // 关联检索配置和SearchView
  6. SearchManager searchManager =
  7. (SearchManager) getSystemService(Context.SEARCH_SERVICE);
  8. SearchView searchView =
  9. (SearchView) menu.findItem(R.id.search).getActionView();
  10. searchView.setSearchableInfo(
  11. searchManager.getSearchableInfo(getComponentName()));
  12. return true;
  13. }

调用getSearchableInfo())返回一个SearchableInfo由检索配置XML文件创建的对象。检索配置与SearchView正确关联后,当用户提交一个搜索请求时,SearchView会以ACTION_SEARCH intent启动一个activity。所以你现在需要一个能过滤这个intent和处理搜索请求的activity。

创建一个检索activity

当用户提交一个搜索请求时,SearchView会尝试以ACTION_SEARCH启动一个activity。检索activity会过滤ACTION_SEARCH intent并在某种数据集中根据请求进行搜索。要创建一个检索activity,在你选择的activity中声明对ACTION_SEARCH intent过滤:

  1. <activity android:name=".SearchResultsActivity" ... >
  2. ...
  3. <intent-filter>
  4. <action android:name="android.intent.action.SEARCH" />
  5. </intent-filter>
  6. ...
  7. </activity>

在你的检索activity中,通过在onCreate())方法中检查ACTION_SEARCH intent来处理它。

Note:如果你的检索activity在single top mode下启动(android:launchMode="singleTop"),也要在onNewIntent())方法中处理ACTION_SEARCH intent。在single top mode下你的activity只有一个会被创建,而随后启动的activity将不会在栈中创建新的activity。这种启动模式很有用,因为用户可以在当前activity中进行搜索,而不用在每次搜索时都创建一个activity实例。

  1. public class SearchResultsActivity extends Activity {
  2. @Override
  3. public void onCreate(Bundle savedInstanceState) {
  4. ...
  5. handleIntent(getIntent());
  6. }
  7. @Override
  8. protected void onNewIntent(Intent intent) {
  9. ...
  10. handleIntent(intent);
  11. }
  12. private void handleIntent(Intent intent) {
  13. if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
  14. String query = intent.getStringExtra(SearchManager.QUERY);
  15. //通过某种方法,根据请求检索你的数据
  16. }
  17. }
  18. ...
  19. }

如果你现在运行你的app,SearchView就能接收用户的搜索请求,以ACTION_SEARCH intent启动你的检索activity。现在就由你来解决如何依据请求来储存和搜索数据。