Using now Otalia Studios Autocomplete for Bank Autocomplete list in AddAccountDialog as it's way more performant than Android's AutoCompleteTextView

This commit is contained in:
dankito 2020-04-23 16:54:34 +02:00
parent 5ce48322a1
commit a8ae3e9006
8 changed files with 111 additions and 73 deletions

View File

@ -5,6 +5,7 @@ ext {
appVersionCode = 1
kotlinVersion = '1.3.72'
kotlinCoroutinesVersion = "1.3.5"
javaUtilsVersion = '1.0.16-SNAPSHOT'
@ -20,6 +21,8 @@ ext {
clansFloatingActionButtonVersion = '1.6.4'
autocompleteVersion = "1.1.0"
multiDexVersion = "2.0.1"
appCompatVersion = "1.1.0"

View File

@ -58,7 +58,10 @@ dependencies {
implementation "com.github.clans:fab:$clansFloatingActionButtonVersion"
implementation "com.otaliastudios:autocomplete:$autocompleteVersion"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutinesVersion"
implementation "net.dankito.utils:android-utils:$androidUtilsVersion", {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk7'

View File

@ -1,53 +1,39 @@
package net.dankito.banking.fints4java.android.ui.adapter
import android.content.Context.LAYOUT_INFLATER_SERVICE
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Filter
import android.widget.Filterable
import kotlinx.android.synthetic.main.list_item_bank_info.view.*
import net.dankito.banking.fints4java.android.R
import net.dankito.banking.ui.presenter.BankingPresenter
import net.dankito.banking.fints4java.android.ui.adapter.filter.BankInfoFilter
import net.dankito.banking.fints4java.android.ui.adapter.viewholder.BankInfoViewHolder
import net.dankito.fints.model.BankInfo
import net.dankito.utils.android.extensions.setTintColor
import net.dankito.utils.android.ui.adapter.ListAdapter
import net.dankito.utils.android.ui.adapter.ListRecyclerAdapter
open class BankListAdapter(protected val presenter: BankingPresenter) : ListAdapter<BankInfo>(), Filterable {
open class BankListAdapter(protected val itemClicked: ((BankInfo) -> Unit)? = null) : ListRecyclerAdapter<BankInfo, BankInfoViewHolder>() {
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View? {
override fun getListItemLayoutId() = R.layout.list_item_bank_info
val item = getItem(position)
override fun createViewHolder(itemView: View): BankInfoViewHolder {
return BankInfoViewHolder(itemView)
}
val inflater = parent?.context?.getSystemService(LAYOUT_INFLATER_SERVICE) as? LayoutInflater
val view = convertView ?: inflater?.inflate(R.layout.list_item_bank_info, parent, false)
view?.let {
override fun bindItemToView(viewHolder: BankInfoViewHolder, item: BankInfo) {
if (item.supportsFinTs3_0) {
view.imgSupportsFints30.setImageResource(R.drawable.ic_check_circle_white_48dp)
view.imgSupportsFints30.setTintColor(R.color.list_item_bank_info_bank_supported)
viewHolder.imgSupportsFints30.setImageResource(R.drawable.ic_check_circle_white_48dp)
viewHolder.imgSupportsFints30.setTintColor(R.color.list_item_bank_info_bank_supported)
}
else {
view.imgSupportsFints30.setImageResource(R.drawable.ic_clear_white_48dp)
view.imgSupportsFints30.setTintColor(R.color.list_item_bank_info_bank_not_supported)
viewHolder.imgSupportsFints30.setImageResource(R.drawable.ic_clear_white_48dp)
viewHolder.imgSupportsFints30.setTintColor(R.color.list_item_bank_info_bank_not_supported)
}
view.txtvwBankName.text = item.name
viewHolder.txtvwBankName.text = item.name
view.txtvwBankCode.text = item.bankCode
viewHolder.txtvwBankCode.text = item.bankCode
view.txtvwBankAddress.text = item.postalCode + " " + item.city
}
viewHolder.txtvwBankAddress.text = item.postalCode + " " + item.city
return view
}
override fun getFilter(): Filter {
return BankInfoFilter(presenter) {
this.setItems(it)
viewHolder.itemView.setOnClickListener {
itemClicked?.invoke(item)
}
}

View File

@ -1,25 +0,0 @@
package net.dankito.banking.fints4java.android.ui.adapter.filter
import android.widget.Filter
import net.dankito.banking.ui.presenter.BankingPresenter
import net.dankito.fints.model.BankInfo
open class BankInfoFilter(protected val presenter: BankingPresenter,
protected val publishResultsCallback: (List<BankInfo>) -> Unit) : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults {
val filteredBanks = presenter.searchBanksByNameBankCodeOrCity(constraint?.toString())
val results = FilterResults()
results.values = filteredBanks
return results
}
override fun publishResults(constraint: CharSequence?, results: FilterResults) {
publishResultsCallback(results.values as List<BankInfo>)
}
}

View File

@ -0,0 +1,35 @@
package net.dankito.banking.fints4java.android.ui.adapter.presenter
import android.content.Context
import androidx.recyclerview.widget.RecyclerView
import com.otaliastudios.autocomplete.RecyclerViewPresenter
import kotlinx.coroutines.*
import net.dankito.banking.fints4java.android.ui.adapter.BankListAdapter
import net.dankito.banking.ui.presenter.BankingPresenter
import net.dankito.fints.model.BankInfo
open class BankInfoPresenter(protected val presenter: BankingPresenter, context: Context) : RecyclerViewPresenter<BankInfo>(context) {
protected val adapter = BankListAdapter { dispatchClick(it) }
protected var lastSearchBanksJob: Job? = null
override fun instantiateAdapter(): RecyclerView.Adapter<*> {
return adapter
}
override fun onQuery(query: CharSequence?) {
lastSearchBanksJob?.cancel()
lastSearchBanksJob = GlobalScope.launch(Dispatchers.IO) {
val filteredBanks = presenter.searchBanksByNameBankCodeOrCity(query?.toString())
withContext(Dispatchers.Main) {
adapter.items = filteredBanks
}
}
}
}

View File

@ -0,0 +1,20 @@
package net.dankito.banking.fints4java.android.ui.adapter.viewholder
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.list_item_bank_info.view.*
open class BankInfoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imgSupportsFints30: ImageView = itemView.imgSupportsFints30
val txtvwBankName: TextView = itemView.txtvwBankName
val txtvwBankCode: TextView = itemView.txtvwBankCode
val txtvwBankAddress: TextView = itemView.txtvwBankAddress
}

View File

@ -2,6 +2,8 @@ package net.dankito.banking.fints4java.android.ui.dialogs
import android.content.Context
import android.content.DialogInterface
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
@ -12,10 +14,12 @@ import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.DialogFragment
import com.otaliastudios.autocomplete.Autocomplete
import com.otaliastudios.autocomplete.AutocompleteCallback
import kotlinx.android.synthetic.main.dialog_add_account.*
import kotlinx.android.synthetic.main.dialog_add_account.view.*
import net.dankito.banking.fints4java.android.R
import net.dankito.banking.fints4java.android.ui.adapter.BankListAdapter
import net.dankito.banking.fints4java.android.ui.adapter.presenter.BankInfoPresenter
import net.dankito.banking.ui.model.responses.AddAccountResponse
import net.dankito.banking.ui.presenter.BankingPresenter
import net.dankito.fints.model.BankInfo
@ -31,8 +35,6 @@ open class AddAccountDialog : DialogFragment() {
protected lateinit var presenter: BankingPresenter
protected lateinit var adapter: BankListAdapter
protected var selectedBank: BankInfo? = null
@ -40,7 +42,6 @@ open class AddAccountDialog : DialogFragment() {
this.presenter = presenter
presenter.preloadBanksAsync()
this.adapter = BankListAdapter(presenter)
val style = if(fullscreen) R.style.FullscreenDialogWithStatusBar else R.style.FloatingDialog
setStyle(STYLE_NORMAL, style)
@ -60,10 +61,7 @@ open class AddAccountDialog : DialogFragment() {
}
protected open fun setupUI(rootView: View) {
rootView.edtxtBankCode.threshold = 1 // will start working from first character
rootView.edtxtBankCode.setAdapter(adapter)
rootView.edtxtBankCode.setOnItemClickListener { _, _, position, _ -> bankSelected(adapter.getItem(position)) }
initBankListAutocompletion(rootView)
rootView.edtxtCustomerId.addTextChangedListener(otherEditTextChangedWatcher)
rootView.edtxtPin.addTextChangedListener(otherEditTextChangedWatcher)
@ -72,6 +70,26 @@ open class AddAccountDialog : DialogFragment() {
rootView.btnCancel.setOnClickListener { dismiss() }
}
private fun initBankListAutocompletion(rootView: View) {
val autocompleteCallback = object : AutocompleteCallback<BankInfo> {
override fun onPopupItemClicked(editable: Editable, item: BankInfo): Boolean {
bankSelected(item)
return true
}
override fun onPopupVisibilityChanged(shown: Boolean) {}
}
Autocomplete.on<BankInfo>(rootView.edtxtBankCode)
.with(6f)
.with(ColorDrawable(Color.WHITE))
.with(autocompleteCallback)
.with(BankInfoPresenter(presenter, rootView.context))
.build()
}
protected open fun addAccount() {
selectedBank?.let { selectedBank -> // should always be non-null at this stage
val customerId = edtxtCustomerId.text.toString()
@ -156,8 +174,6 @@ open class AddAccountDialog : DialogFragment() {
edtxtFinTsServerAddress.setText(bank.pinTanAddress)
edtxtBankCode.clearListSelection()
checkIfRequiredDataEnteredOnUiThread()
if (bank.supportsFinTs3_0 == false) {

View File

@ -13,7 +13,7 @@
android:hint="@string/dialog_add_account_enter_bank_code"
>
<AutoCompleteTextView
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edtxtBankCode"
android:layout_width="match_parent"
android:layout_height="@dimen/dialog_add_account_edit_text_height"