Looking for ideas to implement SearchView in Android. I am using Single Activity Approach in my app. I was following this doc:https://developer.android.com/guide/topics/search/search-dialog
But this adds the overhead of adding new activity.
Currently in my app I have bunch of screens and only on one screen I need to show SearchView.
No need for a new activity.
Create a menu.xml
with the SearchView
:
<?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>
Then in the fragment, you want to display it:
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.
}
})
}
}
I'm assuming that you have setup your navController
with the toolbar, if not, I'll link the documentation to do it, as it is out of the scope of your question, good luck.
N/B: A sample app implementation can be found here
You could have a setup/configuration similar to this:
Step 1: Create a searchable config file in 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"/>
Step 2: In AndroidManifest.xml
, configure your single-activity(MainActivity) to be the searchable activity with launchMode set to 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>
Step 3: In your options menu, add a search menu item
<menu ...>
<item
android:id="@+id/menu_list_search"
android:icon="@drawable/ic_action_search"
android:orderInCategory="1"
android:title="Search"
app:showAsAction="ifRoom" />
</menu>
Step 4: In your MainActivity
(also searchable activity)
/**
* 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)
}
}
}
Step 5: From your list-displaying fragment(the screen where search action will be initiated)
/**
* 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)
}
}
Step 6: Create a search-results displaying fragment(the screen where search query will be sent(from the MainActivity
) and search results shown)
/**
* 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: Some code snippets contains AndroidX's navigation component codes that might not be available in your project
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.