Android 双向数据绑定AdapterViewBindingAdapter(ListView)

Android Two-way data binding AdapterViewBindingAdapter (ListView)

我有一个 ListView 并尝试使用双向数据绑定在使用 Two-Way Attributes

的 ViewModel 中设置 selectedItemPosition

但问题是它不起作用,selected 项目没有设置在 liveData 的值中,我试图观察它并且当我 select listView

中的一项

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}" />

在视图模型中:

   val chosenPosition = MutableLiveData<Int>()

在片段中:

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 
    }

确保您没有忘记在片段中设置绑定生命周期所有者

binding.lifecycleOwner = this

问题:

android:selectedItemPosition 每当项目被 selected 时触发(这并不隐含地包括该项目是 clicked/checked.

ListView 中使用 android:selectedItemPosition 作为双向数据绑定实际上不会在 selected 项目时自动触发,因此不会获取 LiveData触发。

你可以看到,当你创建一个没有任何数据绑定的普通ListView;当您单击一个项目时,这不会触发 selection,请注意单击项目时的以下内容(没有任何内容会以不同的颜色突出显示):

解决方案:

为了解决数据绑定的问题,您需要通过将 OnItemClickListener 注册到 ListView 来明确地 select 那个项目:

binding.listView.setOnItemClickListener { _, _, position, _ ->
    if (position >= 0) { // avoid -1 position calls
        binding.listview.requestFocusFromTouch()
        binding.listview.setItemChecked(position, true)
        binding.listview.setSelection(position)
    }
}

这样,实时数据将被设置为当前 selected 位置:

请注意,当某个项目被 select 编辑时,它现在以浅灰色突出显示,这是因为 selection 已启用: