【问题标题】:Looking for ideas to implement SearchView in Android in a Single Activity App approach寻找在 Android 中以 Single Activity App 方法实现 SearchView 的想法
【发布时间】:2019-10-30 20:50:42
【问题描述】:

寻找在 Android 中实现 SearchView 的想法。 我在我的应用程序中使用单一活动方法。 我在关注这个文档:https://developer.android.com/guide/topics/search/search-dialog

但这增加了添加新活动的开销。

目前在我的应用中,我有一堆屏幕,并且只需要在一个屏幕上显示 SearchView。

【问题讨论】:

    标签: android android-fragments android-intent android-activity android-mvvm


    【解决方案1】:

    不需要新的活动。

    使用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,如果没有,我会链接文档来执行此操作,因为它超出了您的问题范围,祝您好运。

    【讨论】:

    • Hum.. @nkadu1 为什么要删除已解决的复选标记?如果是这样? O.o'
    • Joaquim :它确实帮助我更进一步。谢谢。但我一直在寻找我应该如何在不使用第二个活动的情况下整体使用 SearchView 功能。例如:如果您查看文档,保存查询的唯一方法是在 onCreate 中实现提供程序(通过内容提供程序)......并且有些事情与活动相关。
    • 这不是一个教程网站。这是一个特定的编程问题问答:)。你处理搜索视图的方式和其他方式一样,我什至在那里写了回调
    【解决方案2】:

    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 的导航组件代码,这些代码可能在您的项目中不可用

    【讨论】:

      猜你喜欢
      • 2021-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-02
      • 2011-04-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多