从 Android 3.0 开始,将 SearchView
微件作为应用栏中的一个项是在应用中提供搜索机制的首选方式。与应用栏中的所有项一样,您可以将 SearchView
设定为始终显示、仅在有空间时显示,也可以将其设定为一个可收起操作项,这最初会将 SearchView
显示为一个图标,然后当用户点击该图标时,它会以搜索字段的形式占据整个应用栏的空间。
注意:在本节课后面的部分中,您将了解对于不支持 SearchView
的设备,如何使您的应用与最低为 Android 2.1(API 级别 7)的版本兼容。
将搜索视图添加到应用栏
如需将 SearchView
微件添加到应用栏,请在您的项目中创建一个名为 res/menu/options_menu.xml
的文件,并将以下代码添加到该文件中。此代码定义了如何创建搜索项,例如要使用的图标和项的名称。通过 collapseActionView
属性,您的 SearchView
可以展开以占据整个应用栏的空间,并在未使用时重新收起为一个普通的应用栏项。由于手机设备上的应用栏空间有限,建议使用 collapsibleActionView
属性,以提供更出色的用户体验。
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/search" android:title="@string/search_title" android:icon="@drawable/ic_search" android:showAsAction="collapseActionView|ifRoom" android:actionViewClass="android.widget.SearchView" /> </menu>
注意:如果您的菜单项有现成的 XML 文件,则可以改为将 <item>
元素添加到该文件中。
如需在应用栏中显示 SearchView
,请在 Activity 的 onCreateOptionsMenu()
方法中扩充 XML 菜单资源 (res/menu/options_menu.xml
):
Kotlin
override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.options_menu, menu) return true }
Java
@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.options_menu, menu); return true; }
如果您现在运行应用,会在应用栏中看到 SearchView
,但它不起作用。您现在需要定义 SearchView
的行为方式。
创建可搜索配置
可搜索的配置在 res/xml/searchable.xml
文件中定义了 SearchView
的行为方式。可搜索配置必须至少包含一个 android:label
属性,其值与您的 Android 清单中 <application> 或 <activity> 元素的 android:label
属性的值相同。不过,我们还建议您添加一个 android:hint
属性,以便用户了解可在搜索框中输入的内容:
<?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" />
在应用的清单文件中,声明一个指向 res/xml/searchable.xml
文件的 <meta-data>
元素,以便您的应用知道可以在何处找到该文件。在您要显示 SearchView
的 <activity>
中声明该元素:
<activity ... > ... <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" /> </activity>
在您之前创建的 onCreateOptionsMenu()
方法中,通过调用 setSearchableInfo(SearchableInfo)
将可搜索配置与 SearchView
相关联:
Kotlin
override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.options_menu, menu) // Associate searchable configuration with the SearchView val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager (menu.findItem(R.id.search).actionView as SearchView).apply { setSearchableInfo(searchManager.getSearchableInfo(componentName)) } return true }
Java
@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.options_menu, menu); // Associate searchable configuration with the SearchView SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE); SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView(); searchView.setSearchableInfo( searchManager.getSearchableInfo(getComponentName())); return true; }
调用 getSearchableInfo()
可获取通过可搜索配置 XML 文件创建的 SearchableInfo
对象。可搜索配置与您的 SearchView
正确关联后,SearchView
会在用户提交查询时使用 ACTION_SEARCH
intent 启动 Activity。现在,您需要一个可以过滤此 intent 并处理搜索查询的 Activity。
创建可搜索 Activity
当用户提交搜索查询时,SearchView
会尝试使用 ACTION_SEARCH
启动一个 Activity。可搜索 Activity 可以过滤 ACTION_SEARCH
intent,并在某种数据集内搜索查询。如需创建可搜索 Activity,请声明一个您选择用于过滤 ACTION_SEARCH
intent 的 Activity:
<activity android:name=".SearchResultsActivity" ... > ... <intent-filter> <action android:name="android.intent.action.SEARCH" /> </intent-filter> ... </activity>
在您的可搜索 Activity 中,通过在 onCreate()
方法中检查 ACTION_SEARCH
intent 对其进行处理。
注意:如果您的可搜索 Activity 会在单一顶级模式 (android:launchMode="singleTop"
) 下启动,请也在 onNewIntent()
方法中处理 ACTION_SEARCH
intent。在单一顶级模式下,只能创建 Activity 的一个实例,启动 Activity 的后续调用不会在堆栈上创建新的 Activity。该启动模式非常实用,用户可以通过同一 Activity 执行搜索,而无需每次都创建新的 Activity 实例。
Kotlin
class SearchResultsActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { ... handleIntent(intent) } override fun onNewIntent(intent: Intent) { ... handleIntent(intent) } private fun handleIntent(intent: Intent) { if (Intent.ACTION_SEARCH == intent.action) { val query = intent.getStringExtra(SearchManager.QUERY) //use the query to search your data somehow } } ... }
Java
public class SearchResultsActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { ... handleIntent(getIntent()); } @Override protected void onNewIntent(Intent intent) { ... handleIntent(intent); } private void handleIntent(Intent intent) { if (Intent.ACTION_SEARCH.equals(intent.getAction())) { String query = intent.getStringExtra(SearchManager.QUERY); //use the query to search your data somehow } } ... }
如果您现在运行应用,SearchView
可以接受用户的查询,并使用 ACTION_SEARCH
intent 启动您的可搜索 Activity。现在,您需要确定如何针对查询存储和搜索您的数据。