Android API指南(二)Search篇

本文介绍Search查询。Android提供了两种Search搜索的方式: Search Dialog 和 Search Widget。本文会先给出这两种Search方式的实现步骤,然后再说说最近查询记录、查询建议等内容。

Search Dialog

下面介绍Search对话框的基本使用方式。

点击查看:Search对话框的完整源码

1. 创建一个可搜索的配置

定义一个res/xml/searchable.xml,内容如下:

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

说明:
(01) android:lable,它可搜索配置的一个必要属性。它指向了一个字符串资源,这个字符串应该是应用程序的名字。这个标签只有在你为快速搜索框启用了搜索建议时才会对用户可见。
(02) android:hint,它和在EditText一样,是提示作用。

2. 创建搜索响应Activity

搜索响应Activity的作用是:响应搜索动作,显示搜索结果等。下面是搜索Activity的声明:

    <activity
        android:name=".MySearchImpl"
        android:label="@string/search_impl">
        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
        <meta-data
            android:name="android.app.searchable"
            android:resource="@xml/searchable" />
    </activity>

说明:
(01) android.intent.action.SEARCH,这表明该Activity是用来接收并处理搜索动作的。
(02) meta-data是附加信息。其中,"android.app.searchable"是固定的;而"xml/searchable"则是对应我们在前面定义的"可搜索配置文件res/xml/searchable.xml"。

搜索响应Activity的代码如下:

public class MySearchImpl extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_search);

        Intent intent = getIntent();
        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
            String query = intent.getStringExtra(SearchManager.QUERY);
            TextView v = (TextView)this.findViewById(R.id.message);
            v.setText(query);
        }   
    }   
}

说明:这个Activity纯粹是演示用。它仅仅只是将搜索内容显示到TextView中,并没有指定真正的搜索!

Activity对应的my_search.xml内容如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="@android:drawable/toast_frame">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@android:drawable/stat_notify_chat"
        />

    <TextView
        android:id="@+id/message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:paddingLeft="6dip"
        />

</LinearLayout>

3. 使用搜索对话框

上面已经定义了"对搜索进行响应的Activity",接下来介绍如何定义"发起搜索动作的Activity"。

首先,一个Activity要在manifest中声明支持搜索,并指明搜索响应Activity。如下:

    <activity
        android:name=".SearchTest"
        android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

        <!-- 该activity支持search,可以通过调用onSearchRequested()进行搜索 -->
        <meta-data
            android:name="android.app.default_searchable"
            android:value=".MySearchImpl" />
    </activity>

说明:上面的SearchTest中的meta-data就表明了该Activity支持搜索,并且它对应的搜索响应Activity是MySearchImpl。

有了上面的声明之后,当在SearchTest中调用onSearchRequested()时,就会弹出搜索对话框了!

public class SearchTest extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }   

    public void onClickSearch(View view) {
        Toast.makeText(this, "Click Search", Toast.LENGTH_SHORT).show();
        onSearchRequested();
    }   
}

说明:SearchTest的显示配置文件是main.xml,onClickSearch是Button的点击监听函数。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"
    >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Hello World, SearchTest"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/search"
        android:onClick="onClickSearch"
        />
</LinearLayout>

Search Widget

下面介绍Search Widget的使用方法。它和Search对话框的使用和类似!

点击查看:Search对话框的完整源码

1. 创建一个可搜索的配置

与"Search Dialog"创建一个可搜索的配置一样!

2. 创建搜索响应Activity

与"Search Dialog"创建索相应Activity一样!

3. 使用Search Widget

首先,创建一个带ActionBar的Activity。

声明Activity的主题为带ActionBar的主题,这里使用"Theme.Holo"。

    <activity
        android:name=".SearchTest"
        android:theme="@android:style/Theme.Holo"
        android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>

        <!-- 该activity支持search,可以通过调用onSearchRequested()进行搜索 -->
        <meta-data
            android:name="android.app.default_searchable"
            android:value=".MySearchImpl" />
    </activity>

说明:
(01) meta-data的作用是说明该Activity支持搜索。
(02) android:theme的作用是说明该Activity使用"Theme.Holo"主题,该主题包括ActionBar。

然后,定义Activity对应的menu菜单文件res/menu/option_menu.xml。内容如下:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@+id/menu_search"
        android:title="@string/search"
        android:icon="@drawable/ic_action_search"
        android:showAsAction="ifRoom|collapseActionView"
        android:actionViewClass="android.widget.SearchView" />

</menu>

最后,在点击该Menu的时候弹出SearchView菜单。如下:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.option_menu, menu);

    SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
    SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
    searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
    searchView.setIconifiedByDefault(false);

    return true;
} 

最近查询记录

下面谈谈使用最近查询记录的方法。

点击查看:最近查询记录的完整源码

1. 查询记录类

自定义个一个Content Provider,继承于SearchRecentSuggestionsProvider。

public class MySuggestionProvider extends SearchRecentSuggestionsProvider {
    public final static String AUTHORITY = "com.skw.searchtest.MySuggestionProvider";
    public final static int MODE = DATABASE_MODE_QUERIES;

    public MySuggestionProvider() {
        setupSuggestions(AUTHORITY, MODE);
    }   
}

2. 在manifest中声明该查询类

    <provider android:name=".MySuggestionProvider"
        android:authorities="com.skw.searchtest.MySuggestionProvider" />

3. 修改可用搜索配置

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_label"
    android:hint="@string/search_hint"
    android:searchSuggestAuthority="com.skw.searchtest.MySuggestionProvider"
    android:searchSuggestSelection=" ?" >
</searchable>

4. 保存查询结果

在查询响应Activity中保存查询结果。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.my_search);

    Intent intent = getIntent();
    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        String query = intent.getStringExtra(SearchManager.QUERY);
        TextView v = (TextView)this.findViewById(R.id.message);
        v.setText(query);

        SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
                MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE);
        suggestions.saveRecentQuery(query, null);
    }
}

5. 清空查询结果

SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this,
        MySuggestionProvider.AUTHORITY, MySuggestionProvider.MODE);
suggestions.clearHistory();
by skywang
Previous     Next