ActionMode - SearchView not working (actionView is null)

519 views Asked by At

I recently working on activating SearchView in ActionMode when user click on Search in onOptionsItemSelected.

However, I cant get access to the SearchView as after debugging, its actionView apparently to be null. Can anyone help me with this?

override fun onOptionsItemSelected(item: MenuItem): Boolean {
     R.id.chat_search -> {
          if (searchActionMode == null) {
             searchActionMode = startActionMode(searchActionModeCallBack)
          }
}

ActionModeCallBack

private val searchActionModeCallBack = object: ActionMode.Callback {
        private lateinit var mSearchView: SearchView

        override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
            menuInflater.inflate(R.menu.menu_search_message, menu)

            moreMenuBtn.isVisible = false
            layout_chatbox.hide()

            return true
        }

        override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
            val searchItem = menu?.findItem(R.id.search_item_btn)
            if(searchItem?.actionView != null) {      <---- this seachview.actionView keeps return null
                mSearchView = searchItem.actionView as SearchView
                mSearchView.isIconified = false

                mSearchView.onQueryTextChanged { newText ->

                }
            }

            return true
        }

        override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
            when(item?.itemId) {
                R.id.search_item_up -> {
                    "UP".showToast(this@ChatActivity)
                }
                R.id.search_item_down -> {
                    "DOWN".showToast(this@ChatActivity)
                }
                R.id.search_item_btn -> {
                    "SEARCH".showToast(this@ChatActivity)    <-- when click on "Search" Button, "Search" is toasted.
                }
            }
            return false
        }

        override fun onDestroyActionMode(mode: ActionMode?) {
            searchActionMode = null
            moreMenuBtn.isVisible = true
            layout_chatbox.show()
        }

    }

menu_search_message.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">

    <group android:id="@+id/group_search_mode">

        <item
            android:id="@+id/search_item_btn"
            android:icon="@drawable/ic_baseline_search_24"
            app:showAsAction="always"
            android:title="@string/search"
            app:actionViewClass="androidx.appcompat.widget.SearchView" />

        <item
            android:id="@+id/search_item_up"
            android:icon="@drawable/ic_baseline_arrow_drop_up_24"
            app:showAsAction="always"
            android:title="@string/up"/>

        <item
            android:id="@+id/search_item_down"
            android:icon="@drawable/ic_baseline_arrow_drop_down_24"
            app:showAsAction="always"
            android:title="@string/down"/>

    </group>

</menu>

I used androidx.appcompat.widget.SearchView for all of the SearchView I used. But still I had no idea why I can't access to the SearchView in ActionMode. Please give me some help.

2

There are 2 answers

3
Teo On BEST ANSWER

I had a workaround for this. In my case, I will add a customview to the actionMode's title. Here is my solution.

override fun onOptionsItemSelected(item: MenuItem): Boolean {
     R.id.chat_search -> {
          if (searchActionMode == null) {
             searchActionMode = startActionMode(searchActionModeCallBack)
             val view = layoutInflater.inflate(R.layout.custom_searchview, null)
             searchActionMode?.customView = view   <-- ADD YOUR CUSTOM VIEW

             val etSearch = view.findViewById<EditText>(R.id.et_search)
             etSearch.requestFocus()
             etSearch.doOnTextChanged { text, start, before, count ->
                  // TODO - handle the search query here
             }
   }
}

custom_searchview.xml (Just a simple EditText)

<RelativeLayout
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android" >

    <EditText
        android:id="@+id/et_search"
        android:layout_alignParentStart="true"
        android:maxLines="1"
        android:ellipsize="end"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@null"
        android:padding="10dp"
        android:layout_marginEnd="50dp"
        android:hint="Search..."
        android:textColorHint="@color/colorWhite"
        android:textColor="@color/colorWhite"/>


</RelativeLayout>

menu_search_message.xml (REMOVE THE SEARCH VIEW ITEM)

<?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-->         <-- remove the searchView from xml
<!--        android:id="@+id/search_item_btn"-->
<!--        android:icon="@drawable/ic_baseline_search_24"-->
<!--        android:title="@string/search"-->
<!--        android:enabled="true"-->
<!--        android:actionLayout="@layout/custom_searchview"-->
<!--        app:showAsAction="collapseActionView|always" />-->

    <item
        android:id="@+id/search_item_up"
        android:icon="@drawable/ic_baseline_arrow_drop_up_24"
        android:orderInCategory="2"
        android:title="@string/up"
        app:showAsAction="always" />

    <item
        android:id="@+id/search_item_down"
        android:icon="@drawable/ic_baseline_arrow_drop_down_24"
        android:orderInCategory="3"
        android:title="@string/down"
        app:showAsAction="always" />


</menu>

Final output will be like this

enter image description here

1
Zain On

I faced the same issue before, and what worked for me is to set the ActionView programmatically, not in menu xml.

To do that:

First: Remove the Action ViewClass from your menu

<?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">

    <group android:id="@+id/group_search_mode">

        <item
            android:id="@+id/search_item_btn"
            android:icon="@drawable/ic_baseline_search_24"
            app:showAsAction="always"
            android:title="@string/search"/>
...

Second: Create an instance of a SearchView

Third: Inflate the menu item that you want to set its actionViewClass, and use setActionView(view) to set your instantiated SearchView.

override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
    menuInflater.inflate(R.menu.menu_search_message, menu)

    moreMenuBtn.isVisible = false
    layout_chatbox.hide()
    
    // Step 2:
    val searchView = SearchView(this)
    searchView.setQuery(null, true)
    searchView.queryHint = "Search"

    // Step 3:
    val searchItem = menu?.findItem(R.id.search_item_btn)
    searchItem.setActionView(searchView)

    return true
}