簡體   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