Search code examples
androidkotlinandroid-recyclerviewsearchviewfloating-action-button

SearchView not appearing on Floating Action Button click


How can I open a SearchView widget from Floating Action Button? It seems weird that there appears to be no obvious way of open it outside a menu item. I tried using val searchView = search.expandActionView(search) but that didn't work.

class MainActivity: AppCompatActivity() {
    private lateinit var mAdapter: AdapterServiceUpdates
    private val arrayItems = ArrayList<ItemCompany>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.collapsingtoolbar_and_recyclerview)

        val mCollapsingToolbarLayout = findViewById<CollapsingToolbarLayout>(R.id.myCollapsingToolbarLayout)
        val mToolbar = findViewById<Toolbar>(R.id.myToolbar)
        val mRecyclerView = findViewById<RecyclerView>(R.id.myRecyclerView)

        setSupportActionBar(mToolbar)
        mCollapsingToolbarLayout.title = "MainActivity"
        mToolbar.setNavigationOnClickListener { onBackPressed() }

        val mFab: View = findViewById(R.id.myFab)
        mFab.setOnClickListener { view -> ?
        }

        arrayItems.add(ItemCompany("Item A"))
        arrayItems.add(ItemCompany("Item B"))
        arrayItems.add(ItemCompany("Item C"))
        arrayItems.add(ItemCompany("Item D"))
        arrayItems.add(ItemCompany("Item E"))
        arrayItems.add(ItemCompany("..."))

        mRecyclerView.layoutManager =
                androidx.recyclerview.widget.LinearLayoutManager(this)

        val mListener = AdapterView.OnItemClickListener { _, _, _, _ -> }
        mAdapter = MyAdapter(this, arrayItems, true)

        mRecyclerView.addItemDecoration(
                androidx.recyclerview.widget.DividerItemDecoration(
                        this,
                        LinearLayout.VERTICAL
                )
        )
        mRecyclerView.adapter = mAdapter
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(R.menu.menu_search, menu)
        val search = menu.findItem(R.id.action_search)
        val searchView = search.expandActionView(search)

        // val searchView = search.actionView as SearchView
        searchView.queryHint = "Search"
        searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
            override fun onQueryTextSubmit(query: String?): Boolean {
                return false
            }
            override fun onQueryTextChange(newText: String?): Boolean {
                mAdapter.filter.filter(newText)
                return true
            }
        })
        return super.onCreateOptionsMenu(menu)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            android.R.id.home -> {
                val intent = parentActivityIntent
                intent?.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
                onBackPressed()
                true
            }

            else ->
                super.onOptionsItemSelected(item)
        }
    }
}

enter image description here


Solution

  • You can use searchView.setIconified(false) within the FAB OnClickListener callback to open the SearchView

    How can I do it on class level when Android is expecting it to be declared as an options menu item?

    You can use a lateinit var in the class level as below (notice the changes marked with //<<<<<<< change here notation

    class MainActivity: AppCompatActivity() {
    
        lateinit var searchView: SearchView //<<<<<<< change here
        ...
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.collapsingtoolbar_and_recyclerview)
    
            // rest of your code .....
    
            val mFab: View = findViewById(R.id.myFab)
            mFab.setOnClickListener { view -> ?
                searchView?.setIconified(false) //<<<<<<< change here
            }
    
    
        override fun onCreateOptionsMenu(menu: Menu): Boolean {
            menuInflater.inflate(R.menu.menu_search, menu)
            val searchItem: MenuItem = menu.findItem(R.id.action_search)
            searchView = searchItem.getActionView() as SearchView ///<<<<<<< change here
    
            //  ....
            // .... rest of onCreateOptionsMenu() method