I have made a custom dropdown using TextInputLayout and MaterialAutoCompleteTextView, which I am using multiple times in the same fragment and in multiple fragments as included layouts. I am using DataBinding to pass data between the included layouts. Now the problem is the click event of the dropdown, how can i pass the setOnItemClickListener in layouts included and use it on dropdown. I tried using BindingAdapters and other hacky stuff but unable to achieve this via layout.
dropdown.xml
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="dropDownHint"
type="String" />
<variable
name="dropDownList"
type="java.util.List<String>" />
</data>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textInputLayout"
style="@style/Theme.TextInputLayout.DropDown.Common"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textfield.MaterialAutoCompleteTextView
android:id="@+id/dropDown"
style="@style/Theme.MaterialAutoCompleteTextView.DropDown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:dropDownSelector="@drawable/background_dropdown"
android:hint="@{dropDownHint}"
android:inputType="none"
app:setDropDownBackground="@{@drawable/background_dropdown}"
app:setDropDownItems="@{dropDownList}"
tools:hint="Some Hint" />
</com.google.android.material.textfield.TextInputLayout>
</layout>
layout_textview_dropdown.xml
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="tvText"
type="String" />
<variable
name="dropDownHint"
type="String" />
<variable
name="dropDownList"
type="java.util.List<String>" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include
android:id="@+id/layout_textview"
layout="@layout/textview_heading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tvText="@{tvText}" />
<include
android:id="@+id/layout_dd_surgical"
layout="@layout/dropdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="7dp"
app:dropDownHint="@{dropDownHint}"
app:dropDownList="@{dropDownList}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/layout_textview" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
fragment_step1.xml
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="viewModel"
type="SomeViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/overall_padding"
tools:context=".ui.patient_scan.step1.Step1Fragment">
<include
android:id="@+id/layout_fc"
layout="@layout/layout_textview_dropdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:dropDownHint="@{@string/dd_hint_fc}"
app:dropDownList="@{viewModel.fcList}"
app:layout_constraintBottom_toTopOf="@id/layout_healthFacility"
app:layout_constraintTop_toTopOf="parent"
app:tvText="@{@string/tv_text_fc}" />
<include
android:id="@+id/layout_healthFacility"
layout="@layout/layout_textview_dropdown"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/overall_spacing"
app:dropDownHint="@{@string/dd_hint_healthFacility}"
app:dropDownList="@{viewModel.healthFacility}"
app:layout_constraintBottom_toTopOf="@id/cl_date"
app:layout_constraintTop_toBottomOf="@id/layout_fc"
app:tvText="@{@string/tv_text_healthFacility}" />
...
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
MaterialAutoCompleteTextViewExt.kt
import android.graphics.drawable.Drawable
import androidx.databinding.BindingAdapter
import com.google.android.material.textfield.MaterialAutoCompleteTextView
import com.merisehat.clinicapp.ui.patient_scan.step1.DropDownAdapter
@BindingAdapter("setDropDownBackground")
fun MaterialAutoCompleteTextView.setDropDownBackground(drawable: Drawable) {
setDropDownBackgroundDrawable(drawable)
}
@BindingAdapter("setDropDownItems")
fun MaterialAutoCompleteTextView.setDropDownItems(list: List<String>?) {
if (list.isNullOrEmpty()) return
val adapter = DropDownAdapter(context, list)
setAdapter(adapter)
setOnItemClickListener { _, _, position, _ ->
adapter.setSelectedItem(position)
}
}
DropDownAdapter.kt
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import androidx.databinding.DataBindingUtil
import com.merisehat.clinicapp.data.models.api.dropdown.Country
import com.merisehat.clinicapp.databinding.ItemDropdownBinding
class DropDownAdapter(context: Context, list: List<String>):
ArrayAdapter<String>(context, 0, list) {
private var selectedItemPosition = -1
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val item = getItem(position)
val binding: ItemDropdownBinding = if (convertView == null) {
val inflater = LayoutInflater.from(context)
ItemDropdownBinding.inflate(inflater, parent, false)
} else {
DataBindingUtil.getBinding(convertView)!!
}
binding.item = item
binding.isSelected = position == selectedItemPosition
return binding.root
}
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
return getView(position, convertView, parent)
}
fun setSelectedItem(position: Int) {
selectedItemPosition = position
notifyDataSetChanged()
}
}
I have a solution through which I can achieve the setOnItemClickListener and that is via Fragment but I am looking for a clean solution which i can implement via databinding layouts so I don't have to use Fragments