Add SearchView To Android Toolbar

May 22, 2018

There are 2 ways to do this

Add SearchView by Menu

Add android.widget.SearchView to menu xml (e.g. menu_main.xml).

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.luasoftware.luapass.MainActivity">

    <item android:id="@+id/action_search"
        android:title="Search"
        android:icon="@drawable/ic_search_white_24dp"
        app:showAsAction="collapseActionView|always"
        app:actionViewClass="androidx.appcompat.widget.SearchView" />

    <item
        android:id="@+id/action_settings"
        android:title="@string/action_settings"
        app:showAsAction="never" />

</menu>

2019-04-13: Use app:actionViewClass="androidx.appcompat.widget.SearchView" instead of app:actionViewClass="android.widget.SearchView". android.widget.SearchView has outdated UI and some UI bugs.

Activity code to access SearchView.

By default, a search icon is shown, where it shall expand into search field on click.

If you want the search field to always be visible, then call setIconifiedByDefault(false).

import androidx.appcompat.widget.SearchViewclass MainActivity : AppCompatActivity() {    override fun onCreateOptionsMenu(menu: Menu): Boolean {        menuInflater.inflate(R.menu.menu_main, menu)        val searchItem =  menu.findItem(R.id.action_search)        // Optional: if you want to expand SearchView from icon to edittext view        searchItem.expandActionView()        val searchView = searchItem.actionView as SearchView    }}

Add SearchView in AppBarLayout/Toolbar

  • Add SearchView within Toolbar
  • Add focusable LinearLayout to prevent Keyboard from popup on activity load
  • Set toolbar contentInsetLeft/Start and contentInsetLeft/Start to 0dp to reduce left padding of SearchView
<android.support.design.widget.CoordinatorLayout ..>
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:contentInsetLeft="0dp"
            android:contentInsetStart="0dp"
            app:contentInsetLeft="0dp"
            app:contentInsetStart="0dp"
            app:popupTheme="@style/AppTheme.PopupOverlay">

            <!-- dummy to catch focus -->
            <LinearLayout
                android:focusable="true"
                android:focusableInTouchMode="true"
                android:layout_width="0px"
                android:layout_height="0px"/>

            <android.support.v7.widget.SearchView
                android:id="@+id/search"
                android:layout_height="wrap_content"
                android:layout_width="match_parent"
                android:nextFocusUp="@id/search"
                android:nextFocusLeft="@id/search"
                />

        </android.support.v7.widget.Toolbar>

    </android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
// expand searchView as EditText (default is a search icon)search.setIconifiedByDefault(false)search.queryHint = "Search"

Delay trigger for search query text changes

The sample below listen for search query as it is typed, delaying the trigger event from 300ms to 1s depending on the length of the string.

search.setOnQueryTextListener(object: SearchView.OnQueryTextListener {            var timer = Timer()            override fun onQueryTextSubmit(query: String?): Boolean {                return false            }            override fun onQueryTextChange(newText: String): Boolean {                timer.cancel()                val sleep = when(newText.length) {                    1 -> 1000L                    2,3 -> 700L                    4,5 -> 500L                    else -> 300L                }                timer = Timer()                timer.schedule(sleep) {                    if (!newText.isNullOrEmpty()) {                        // search                    }                }                return true            }        })

NOTE: import kotlin.concurrent.schedule is required for timer.schedule.

References:

❤️ Is this article helpful?

Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.

Do send some 💖 to @d_luaz or share this article.

✨ By Desmond Lua

A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz

👶 Apps I built

Travelopy - discover travel places in Malaysia, Singapore, Taiwan, Japan.