oligazar
6/5/2017 - 4:48 AM

SearchView in Android Toolbar

SearchView in Android Toolbar

  <!--styling searchview-->
  <!--https://philio.me/styling-the-searchview-with-appcompat-v21/-->
  <!--changing background color-->
  <!--https://stackoverflow.com/questions/27240200/changing-the-background-color-of-searchview-autocomplete-dropdown-->
  <style parent="Theme.AppCompat.Light.DarkActionBar" name="AppTheme">
      <!-- Customize your theme here. -->
      <item name="colorPrimary">@color/colorPrimary</item>
      <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
      <item name="colorAccent">@color/colorAccent</item>
      <item name="searchViewStyle">@style/AppTheme.SearchViewStyle</item>
  </style>
  
  <style name="AppTheme.SearchViewStyle" parent="Widget.AppCompat.SearchView">
      <!-- Gets rid of the search icon -->
      <item name="searchIcon">@drawable/ic_search</item>
      <!-- Gets rid of the "underline" in the text -->
      <item name="queryBackground">@color/colorWhite</item>
      <!-- Gets rid of the search icon when the SearchView is expanded -->
      <!--<item name="searchHintIcon">@null</item>-->
      <!-- The hint text that appears when the user has not typed anything -->
      <!--<item name="queryHint">@string/search_hint</item>-->
  </style>
  <!-- ToolBar -->
<style name="ToolBarStyle" parent="Theme.AppCompat">
    <item name="android:textColorPrimary">@android:color/white</item>
    <item name="android:textColorSecondary">@android:color/white</item>
    <item name="actionMenuTextColor">@android:color/white</item>
    <item name="android:dropDownItemStyle">@style/myDropDownItemStyle</item>
    <item name="android:dropDownListViewStyle">@style/myDropDownListViewStyle</item>
</style>

<style name="myDropDownItemStyle" parent="Widget.AppCompat.DropDownItem.Spinner">
    <item name="android:textColor">@color/secondary_text_default_material_light</item>
    <item name="android:textSize">14dp</item>
</style>

<style name="myDropDownListViewStyle" parent="Widget.AppCompat.ListView.DropDown">
    <item name="android:background">#FFF</item>
</style>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity"
    xmlns:yourapp="http://schemas.android.com/apk/res-auto">

    <item android:id="@+id/action_search"
        android:orderInCategory="100"
        android:title="@string/action_search"
        android:icon="@drawable/ic_search"
        yourapp:showAsAction="ifRoom|collapseActionView"
        yourapp:actionViewClass="android.support.v7.widget.SearchView" />

</menu>
import android.app.SearchManager
import android.content.Context
import android.database.MatrixCursor
import android.os.Bundle
import android.os.Environment
import android.provider.BaseColumns
import android.support.v4.app.Fragment
import android.support.v4.content.ContextCompat
import android.support.v4.view.MenuItemCompat
import android.support.v4.widget.CursorAdapter
import android.support.v7.widget.SearchView
import android.text.InputType
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.widget.EditText
import us.kostenko.mnemonikon.R
import us.kostenko.mnemonikon.codes.utility.AppConstant
import us.kostenko.mnemonikon.codes.utility.Image
import us.kostenko.mnemonikon.codes.utility.Utils
import java.io.File
import java.util.*

/**
 * Created by Admin on 5/30/17.
 * Base fragment with search functionality
 */

abstract class BaseSearchableFragment: Fragment() {

    lateinit var suggestionAdapter: CursorAdapter
    private val SEARCH_TAG = "searchTag"
    lateinit var util: Utils
    lateinit var images: ArrayList<Image>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        util = Utils(context)
        setHasOptionsMenu(true)
    }

    companion object {
        val SUGGESTION_COLUMN_NAME = "suggestion"
        val SUGGESTION_COLUMN_PATH = "path"
    }

    override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
//        val searchItem = menu?.add(0, search, 0, R.string.action_search)
//        searchItem?.setIcon(R.drawable.ic_action_search)

        inflater?.inflate(R.menu.menu_search, menu)
        val searchItem = menu?.findItem(R.id.search)
        val searchView = MenuItemCompat.getActionView(searchItem) as SearchView
        
        // alternatively
        // val searchView = SearchView(activity)
        // val item = menu.add(Menu.NONE, cMenuItemSearch, Menu.NONE, getString(R.string.menu_search))
        //         .setActionView(searchView)
        //         .apply { setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS) }
                
        val searchManager = activity.getSystemService(Context.SEARCH_SERVICE) as SearchManager
//        searchView.queryHint = resources.getString(R.string.search_hint)
        searchView.setSearchableInfo(searchManager.getSearchableInfo(activity.componentName))

        // set hint color
        val editText = searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text) as EditText
        editText.setHintTextColor(ContextCompat.getColor(activity, R.color.colorText))
        editText.inputType = InputType.TYPE_CLASS_NUMBER

        // set up hints
        suggestionAdapter = SearchAdapter(context, null)

        searchView.suggestionsAdapter = suggestionAdapter

        searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
            override fun onQueryTextSubmit(query: String): Boolean {
                loadSearchResultsFragment(query)
                return false
            }

            override fun onQueryTextChange(query: String): Boolean {
                loadSuggestions(query, suggestionAdapter)
                return false
            }
        })

        searchView.setOnSuggestionListener(object : SearchView.OnSuggestionListener {
            override fun onSuggestionSelect(position: Int) = false

            override fun onSuggestionClick(position: Int): Boolean {
                loadSearchResultsFragment(getQueryFromCursor(position))
                return false
            }
        })

        MenuItemCompat.setOnActionExpandListener(searchItem, object : MenuItemCompat.OnActionExpandListener {
            override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
                setItemsVisibility(menu, searchItem, true)
                return true
            }  // Return true to collapse action view
            override fun onMenuItemActionExpand(item: MenuItem): Boolean {
                setItemsVisibility(menu, searchItem, false)
                return true
            }  // Return true to expand action view
        })
    }

    private fun loadSearchResultsFragment(query: String) {

//        val position = images.indexOf(images.first { it.name == query })
//        val ft = activity.supportFragmentManager.beginTransaction()
//        val newFragment = SlideshowDialogFragment.newInstance(ArrayList(images.map { it.path }), position)
//        newFragment.show(ft, "slideshow")
    }

    private fun getQueryFromCursor(position: Int): String {
        var query = ""
        val cursor = suggestionAdapter.cursor
        if (suggestionAdapter.cursor.moveToPosition(position)) {
            query = cursor.getString(cursor.getColumnIndex(SUGGESTION_COLUMN_NAME))
        }
        return query
    }

    /** Presenter */

    fun loadSuggestions(query: String, adapter: CursorAdapter) {

        val c = MatrixCursor(arrayOf(BaseColumns._ID, SUGGESTION_COLUMN_NAME, SUGGESTION_COLUMN_PATH))
        val folderName: String
        if (query.length == 2) {
            folderName = "00--99"
        } else {
            folderName = "00--99"
        }

        val basePath = Environment.getExternalStorageDirectory().toString() + File.separator + AppConstant.PHOTO_MNEMO
        images = util.getImages(basePath + File.separator + folderName)
        images.indices
                .filter { images[it].name.contains(query) }
                .forEach { c.addRow(arrayOf(it, images[it].name, images[it].path)) }

        adapter.changeCursor(c)
        return
    }

    private fun setItemsVisibility(menu: Menu?, exception: MenuItem?, visible: Boolean) {
        if (menu == null) return
        (0..menu.size() - 1)
                .map { menu.getItem(it) }
                .filter { it !== exception }
                .forEach { it?.isVisible = visible }
    }
}