繁体   English   中英

寻找在 Android 中以单一活动应用程序方法实现 SearchView 的想法

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM