[英]Looking for ideas to implement SearchView in Android in a Single Activity App approach
寻找在 Android 中实现 SearchView 的想法。 我在我的应用程序中使用单一活动方法。 我在关注这个文档:https://developer.android.com/guide/topics/search/search-dialog
但这增加了添加新活动的开销。
目前在我的应用程序中,我有一堆屏幕,只需要在一个屏幕上显示 SearchView。
不需要新的活动。
使用SearchView
创建一个menu.xml
:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_search"
android:icon="@drawable/ic_search"
android:title="@string/search"
android:menuCategory="secondary"
app:showAsAction="ifRoom|collapseActionView"
app:actionViewClass="androidx.appcompat.widget.SearchView"/>
</menu>
然后在片段中,您要显示它:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.your_menu_with_search, menu)
setupSearchView(menu.findItem(R.id.action_search).actionView as SearchView)
}
private fun setupSearchView(searchView: SearchView) {
searchView.queryHint = "Your option query hint"
searchView.setOnQueryTextListener(object: SearchView.OnQueryTextListener {
override fun onQueryTextChange(newText: String?): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onQueryTextSubmit(query: String?): Boolean {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
})
}
}
我假设您已经使用工具栏设置了navController
,如果没有,我将链接文档来执行此操作,因为它不在您问题的 scope 范围内,祝您好运。
N/B:可以在此处找到示例应用程序实现
您可以进行类似于以下的设置/配置:
第 1 步:在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}")
}
}
Search Query Flow: list-displaying fragment -> MainActivity(searchable activity) -> result-displaying fragment
N/B:一些代码片段包含 AndroidX 的导航组件代码,这些代码可能在您的项目中不可用
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.