I have a ListView
and trying to use two-way data binding to set the selectedItemPosition
in a ViewModel using Two-Way Attributes
But the problem is it doesn't work, the selected item doesn't set in the Value of the liveData, I tried to observe it and the value never changes when i select an item in the listView
data binding in XML:
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="@dimen/_150sdp"
android:nestedScrollingEnabled="true"
tools:listheader="@tools:sample/lorem"
tools:visibility="visible"
android:choiceMode="singleChoice"
android:selectedItemPosition="@={viewModel.chosenPosition}" />
in the ViewModel:
val chosenPosition = MutableLiveData<Int>()
in the Fragment:
binding.viewModel = viewModel
binding.lifecycleOwner = viewLifecycleOwner
binding.teamsListView.adapter = ArrayAdapter(
context,
R.layout.list_item_choice, teamsNames
)
viewModel.chosenPosition.observe(viewLifecycleOwner) {
Timber.d("chosen position = $it") //never triggers when I select an item in the ListView
}
android:selectedItemPosition
is triggered whenever an item is selected (this doesn't implicitly include that the item is clicked/checked.
Using android:selectedItemPosition
as a two-way data binding in a ListView
doesn't actually automatically triggered when an item is selected, and therefore the LiveData doesn't get triggered.
You can see that when you create a normal ListView
without any data binding; when you click an item, this won't trigger the selection, notice the below when an item is clicked (nothing get highlighted with a different color):
In order to solve that for the sake of data binding, you need to explicitly do select the that item whenever it is clicked by registering OnItemClickListener
to the ListView
:
binding.listView.setOnItemClickListener { _, _, position, _ ->
if (position >= 0) { // avoid -1 position calls
binding.listview.requestFocusFromTouch()
binding.listview.setItemChecked(position, true)
binding.listview.setSelection(position)
}
}
This way the live data will be set to the current selected position:
Notice when an item is selected, it's now highlighted with a light grey that is because the selection is enabled: