Skip to content

Instantly share code, notes, and snippets.

@milhauscz
Last active July 10, 2022 11:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save milhauscz/e227680bebc498d0e41f8dc7c164a155 to your computer and use it in GitHub Desktop.
Save milhauscz/e227680bebc498d0e41f8dc7c164a155 to your computer and use it in GitHub Desktop.
Custom adapter for MaterialSpinner
/**
* Custom adapter for [MaterialSpinner]. Just implement [getView] to provide the given View, e. g.
* by using [inflater]. In case of data binding, the binding object can be set as the given View's
* tag to be able to retrieve it when reusing the given View and implement custom viewholder pattern.
* [selectedItemPosition] can be used for updating the selected View's UI. When used together with
* [MaterialSpinner], [selectedItemPosition] is updated automatically and [notifyDataSetChanged] is called.
*
* Created by Milos Cernilovsky on 4/21/21
*/
abstract class MaterialSpinnerAdapter<T>(context: Context, private val objects: List<T>) : BaseAdapter(), Filterable {
// fake filter to implement Filterable (required by MaterialSpinner's AutocompleteTextView parent)
private val _filter: Filter by lazy {
object : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults {
return FilterResults()
}
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
}
}
}
val inflater: LayoutInflater = LayoutInflater.from(context)
var selectedItemPosition = 0
set(value) {
field = value
notifyDataSetChanged()
}
override fun getCount(): Int = objects.size
override fun getItem(position: Int): T = objects[position]
override fun getItemId(position: Int): Long = position.toLong()
override fun getFilter(): Filter = _filter
}
@Hmerman6006
Copy link

Hmerman6006 commented Jul 10, 2022

I am receiving the following error when initialising the adapter:

The expression 'viewModelSelectedItemPosition.getValue()' cannot be inverted, so it cannot be used in a two-way binding

Details: There is no inverse for method getValue, you must add an @InverseMethod annotation to the method to indicate which method should be used when using it in two-way binding expressions

Your example code lacks implementation example:

class SpinnerViewModel: ViewModel() {

    private val _selectedItemPosition = MutableLiveData<Int>(0)
    val selectedItemPosition: LiveData<Int> = _selectedItemPosition
    var items: List<ExampleItem>? = null
}

I initialise the adapter in onCreate function of activity:

val sItems = arrayListOf<ExampleItem>()
sItems.add(ExampleItem("This", false))
sItems.add(ExampleItem("That", false))
sItems.add(ExampleItem("WhatsIt", false))

binding?.materialSpinner?.items?.let { bindItems(it, sItems) }

binding?.materialSpinner?.items?.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
    override fun onNothingSelected(p0: AdapterView<*>?) {
        Log.d("$TAG onNothingSelected", p0.toString())
     }

     override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {
         Log.d("$TAG onItemSelected", p0.toString())
         Log.d("$TAG onItemSelected", p1.toString())
         Log.d("$TAG onItemSelected", p2.toString())
         Log.d("$TAG onItemSelected", p3.toString())
     }
 }

Can you give some pointers?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment