N/B:可以在here找到示例应用实现
您可以进行类似的设置/配置:
第一步:在xml/searchable.xml中创建一个可搜索的配置文件
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:hint="@string/search_hint"
android:label="@string/app_name"/>
第 2 步:在AndroidManifest.xml 中,将您的单一活动(MainActivity)配置为可搜索活动,并将launchMode 设置为singleTop
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
<application ...>
<!-- launchMode=singleTop is IMPORTANT to avoid relaunching MainActivity every time search is initiated -->
<activity
android:name=".MainActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable" />
</activity>
</application>
</manifest>
第 3 步:在您的选项菜单中,添加一个搜索菜单项
<menu ...>
<item
android:id="@+id/menu_list_search"
android:icon="@drawable/ic_action_search"
android:orderInCategory="1"
android:title="Search"
app:showAsAction="ifRoom" />
</menu>
第 4 步:在您的 MainActivity(也可搜索活动)中
/**
* Single activity serving as searchable-activity too
*/
class MainActivity : AppCompatActivity() {
private lateinit var binding: MainActivityBinding
private val navController: NavController by lazy {
findNavController(R.id.navigation_host)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = MainActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
handleIntent(intent)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
handleIntent(intent)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean =
item.onNavDestinationSelected(navController) || super.onOptionsItemSelected(item)
override fun onSearchRequested(): Boolean {
val customAppData = Bundle().apply{
putString("key1", "value1")
}
startSearch(null, false, customAppData, false)
return true
// return super.onSearchRequested() // Use when there is no need to send custom app data
}
private fun handleIntent(intent: Intent) {
// Verify the action and get the query
if (Intent.ACTION_SEARCH == intent.action) {
val query = intent.getStringExtra(SearchManager.QUERY) ?: return
// Pass the [query] received to a fragment in which actual data-searching process will be done
val navOptions = NavOptions.Builder().setLaunchSingleTop(true).build()
navController.navigate(R.id.dest_search_results, SearchResultsFragmentArgs(query=query).toBundle(), navOptions)
}
}
}
第 5 步:从您的列表显示片段(将启动搜索操作的屏幕)
/**
* List displaying fragment
*/
class SearchInitiatorFragment: Fragment(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Needed to help show options menu from fragments
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.list_menu, menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
/*
Launch SearchDialog when "search" menu item is clicked.
N/B: I chose to go with a SearchDialog instead of SearchView since it was easier for me
to send/pass custom app-data to my searchable activity (MainActivity in this case) after
submiting a search query
*/
R.id.menu_list_search -> activity?.onSearchRequested() ?: false
else -> super.onOptionsItemSelected(item)
}
}
第6步:创建一个搜索结果显示片段(搜索查询将被发送的屏幕(来自MainActivity)并显示搜索结果)
/**
* Search results displaying fragment
*/
class SearchResultsFragment: Fragment(){
private val args: SearchResultsFragmentArgs by navArgs()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Log.i("SearchResultsFragment", "Received Query: ${args.query}")
}
}
搜索查询流程: 列表显示片段 -> MainActivity(可搜索活动) -> 结果显示片段
N/B:某些代码 sn-ps 包含 AndroidX 的导航组件代码,这些代码可能在您的项目中不可用