Added a SearchView to MerchantsFragment's Toolbar, with an autocomplete feature that once the user starts writing shows suggestions to the user and listens when he selects one of those suggestions. The suggestions show dummy data for now, but it will query the database to obtain such suggestions.
This commit is contained in:
parent
8aab7c03ac
commit
db58d601f4
2 changed files with 75 additions and 2 deletions
|
@ -2,22 +2,28 @@ package cy.agorise.bitsybitshareswallet.fragments
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.SearchManager
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.database.Cursor
|
||||||
|
import android.database.MatrixCursor
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import com.google.android.gms.maps.GoogleMap
|
import com.google.android.gms.maps.GoogleMap
|
||||||
import com.google.android.gms.maps.OnMapReadyCallback
|
import com.google.android.gms.maps.OnMapReadyCallback
|
||||||
import com.google.android.gms.maps.SupportMapFragment
|
import com.google.android.gms.maps.SupportMapFragment
|
||||||
|
|
||||||
import cy.agorise.bitsybitshareswallet.R
|
import cy.agorise.bitsybitshareswallet.R
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
|
import android.provider.BaseColumns
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.widget.PopupWindow
|
import android.widget.PopupWindow
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.appcompat.widget.SwitchCompat
|
import androidx.appcompat.widget.SwitchCompat
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.cursoradapter.widget.SimpleCursorAdapter
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProviders
|
import androidx.lifecycle.ViewModelProviders
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
|
@ -28,6 +34,7 @@ import com.google.maps.android.MarkerManager
|
||||||
import com.google.maps.android.clustering.Cluster
|
import com.google.maps.android.clustering.Cluster
|
||||||
import com.google.maps.android.clustering.ClusterItem
|
import com.google.maps.android.clustering.ClusterItem
|
||||||
import com.google.maps.android.clustering.ClusterManager
|
import com.google.maps.android.clustering.ClusterManager
|
||||||
|
import com.jakewharton.rxbinding3.appcompat.queryTextChangeEvents
|
||||||
import cy.agorise.bitsybitshareswallet.database.entities.Merchant
|
import cy.agorise.bitsybitshareswallet.database.entities.Merchant
|
||||||
import cy.agorise.bitsybitshareswallet.database.entities.Teller
|
import cy.agorise.bitsybitshareswallet.database.entities.Teller
|
||||||
import cy.agorise.bitsybitshareswallet.utils.Constants
|
import cy.agorise.bitsybitshareswallet.utils.Constants
|
||||||
|
@ -35,10 +42,13 @@ import cy.agorise.bitsybitshareswallet.utils.MerchantClusterRenderer
|
||||||
import cy.agorise.bitsybitshareswallet.utils.TellerClusterRenderer
|
import cy.agorise.bitsybitshareswallet.utils.TellerClusterRenderer
|
||||||
import cy.agorise.bitsybitshareswallet.utils.toast
|
import cy.agorise.bitsybitshareswallet.utils.toast
|
||||||
import cy.agorise.bitsybitshareswallet.viewmodels.MerchantViewModel
|
import cy.agorise.bitsybitshareswallet.viewmodels.MerchantViewModel
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
|
||||||
class MerchantsFragment : Fragment(), OnMapReadyCallback {
|
class MerchantsFragment : Fragment(), OnMapReadyCallback, SearchView.OnSuggestionListener {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "MerchantsFragment"
|
private const val TAG = "MerchantsFragment"
|
||||||
|
@ -53,6 +63,11 @@ class MerchantsFragment : Fragment(), OnMapReadyCallback {
|
||||||
|
|
||||||
private var mMarkerManager: MarkerManager? = null
|
private var mMarkerManager: MarkerManager? = null
|
||||||
|
|
||||||
|
/** Keeps track of all RxJava disposables, to make sure they are all disposed when the fragment is destroyed */
|
||||||
|
private var mDisposables = CompositeDisposable()
|
||||||
|
|
||||||
|
private var mSearchView: SearchView? = null
|
||||||
|
|
||||||
// Cluster managers to create custom merchants and tellers clusters with a custom behavior too
|
// Cluster managers to create custom merchants and tellers clusters with a custom behavior too
|
||||||
private var mMerchantClusterManager: ClusterManager<Merchant>? = null
|
private var mMerchantClusterManager: ClusterManager<Merchant>? = null
|
||||||
private var mTellerClusterManager: ClusterManager<Teller>? = null
|
private var mTellerClusterManager: ClusterManager<Teller>? = null
|
||||||
|
@ -128,6 +143,51 @@ class MerchantsFragment : Fragment(), OnMapReadyCallback {
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
inflater.inflate(R.menu.menu_merchants, menu)
|
inflater.inflate(R.menu.menu_merchants, menu)
|
||||||
|
|
||||||
|
// Adds listener for the SearchView
|
||||||
|
val searchItem = menu.findItem(R.id.menu_search)
|
||||||
|
mSearchView = searchItem.actionView as SearchView
|
||||||
|
mSearchView?.suggestionsAdapter = SimpleCursorAdapter(context, android.R.layout.simple_list_item_1, null,
|
||||||
|
arrayOf(SearchManager.SUGGEST_COLUMN_TEXT_1), intArrayOf(android.R.id.text1))
|
||||||
|
|
||||||
|
// Add listener to changes in the SearchView's text to update the suggestions
|
||||||
|
mSearchView?.queryTextChangeEvents()
|
||||||
|
?.skipInitialValue()
|
||||||
|
?.debounce(500, TimeUnit.MILLISECONDS)
|
||||||
|
?.map { it.queryText.toString().toLowerCase() }
|
||||||
|
?.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
?.subscribe {
|
||||||
|
updateSearchViewSuggestions(it)
|
||||||
|
}?.let {
|
||||||
|
mDisposables.add(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
mSearchView?.setOnSuggestionListener(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateSearchViewSuggestions(query: String) {
|
||||||
|
// TODO make call to the db to obtain the list of merchants/tellers
|
||||||
|
val cursor = MatrixCursor(arrayOf(BaseColumns._ID, SearchManager.SUGGEST_COLUMN_TEXT_1))
|
||||||
|
|
||||||
|
for (i in 1..3) {
|
||||||
|
cursor.addRow(arrayOf(i.toString(), "Merchant $i"))
|
||||||
|
}
|
||||||
|
|
||||||
|
mSearchView?.suggestionsAdapter?.changeCursor(cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSuggestionSelect(position: Int): Boolean {
|
||||||
|
return onSuggestionClick(position)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSuggestionClick(position: Int): Boolean {
|
||||||
|
val cursor = mSearchView?.suggestionsAdapter?.getItem(position) as Cursor?
|
||||||
|
val name = cursor?.getString(cursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1)) ?: ""
|
||||||
|
cursor?.close()
|
||||||
|
|
||||||
|
context?.toast(name)
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
|
||||||
|
@ -418,4 +478,10 @@ class MerchantsFragment : Fragment(), OnMapReadyCallback {
|
||||||
|
|
||||||
dismissPopupWindow()
|
dismissPopupWindow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
|
||||||
|
if (!mDisposables.isDisposed) mDisposables.dispose()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,13 @@
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_search"
|
||||||
|
android:icon="@drawable/ic_search"
|
||||||
|
android:title="@string/title_search"
|
||||||
|
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
||||||
|
app:showAsAction="always"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_filter"
|
android:id="@+id/menu_filter"
|
||||||
android:icon="@drawable/ic_more_vert"
|
android:icon="@drawable/ic_more_vert"
|
||||||
|
|
Loading…
Reference in a new issue