将复选框状态保存在recycleview双向数据绑定中

时间:2019-09-05 11:15:29

标签: android data-binding android-recyclerview viewmodel

我有一个fragment,它有一个垂直的类别选择器(基本上是带有复选框的水平recycleview),用户可以一次选择一个类别。 fragment viewmodel扩展了ViewModel

在通过数据绑定实现recycleview adapter的同时,我注意到我需要使用两种方式的databinding来保存所选checkbox(类别)的状态。

我添加了BaseObservable,它将设置并保存checkbox的状态,而该状态应能正常工作。现在,我很难说出一次只能检查一个checkbox的逻辑。

GenreObservable

class GenreObservable : BaseObservable()
{

    lateinit var data : Genre
    var index : Int=0
    var prevIndex : Int = 0

    fun bindGenre(index : Int,data : Genre)
    {
        this.index = index
        this.data = data
    }

    @Bindable
    fun getGenreChecked(): Boolean {
        return data.selectedGenre
    }

    fun setGenreChecked(isChecked: Boolean) {
        data.selectedGenre = isChecked

        if(isChecked)
        {

        }

        notifyPropertyChanged(BR.viewModel)
    }

    @Bindable
    fun getGenreName() : String
    {
        return data.name!!
    }

    @Bindable
    fun getGenreId() : Int
    {
        return data.id
    }

}

GenreRecycleAdapter

class GenreRecycleAdapter : RecyclerView.Adapter<GenreRecycleAdapter.GenreHolder>(){

    private lateinit var data: List<Genre>
    private var selectedGenreIndex = -1

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GenreHolder {
        val binding: GenreItemBinding = DataBindingUtil.inflate(
            LayoutInflater.from(parent.context),
            R.layout.genre_item,
            parent,
            false
        )
        return GenreRecycleAdapter.GenreHolder(binding)
    }

    override fun getItemCount(): Int {
        return if(::data.isInitialized) data.size else 0
    }

    override fun onBindViewHolder(holder: GenreHolder, position: Int) {
        holder.bind(position,data[position])
    }

    fun setData(data : List<Genre>)
    {
        this.data = data
        notifyDataSetChanged()
    }

    fun setCheckedState(index : Int, state : Boolean)
    {
        data[index].selectedGenre = state
    }

    class GenreHolder(private val binding: GenreItemBinding) :

        RecyclerView.ViewHolder(binding.root) {
        private val viewModel = GenreObservable()

        fun bind(index : Int, data: Genre) {
            viewModel.bindGenre(index,data)
            binding.viewModel = viewModel
        }
    }
}

TopSeriesViewModel

class TopSeriesViewModel : BaseViewModel()
{
    val genreName : MutableLiveData<String> = MutableLiveData()
    val genreIndex : MutableLiveData<Int> = MutableLiveData()
    val genreState : MutableLiveData<Boolean> = MutableLiveData()

    val gAdapter : GenreRecycleAdapter = GenreRecycleAdapter()

    @Inject
    lateinit var topSeriesApi : TopSeriesApi

    private var selectedGenreIndex : Int = 0

    init {
        loadGenres()
    }

    private fun loadGenres()
    {
        subscription = topSeriesApi.getGenres(API_KEY_V3,LANG)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnSubscribe { onRetrievePostListStart() }
            .doOnTerminate { onRetrievePostListFinish() }
            .subscribe(
                { result->onRetrievePostListSuccess(result) },
                { onRetrievePostListError() }
            )

    }

    fun bindGenre(index : Int,gen : Genre)
    {
        genreName.value = gen.name
        genreIndex.value = index
        genreState.value = gen.selectedGenre
    }

    private fun onRetrievePostListFinish() {

    }

    private fun onRetrievePostListError() {
        Log.d("anton","onRetrievePostListError")
    }

    private fun onRetrievePostListStart() {

    }

    private fun onRetrievePostListSuccess(result: GenreList) {
        val data = result.genres!!
//        val all = Genre(-1,"All",true)///"All" using context

//        data.add
        data[0].selectedGenre = true

        gAdapter.setData(data)
    }

    val checkedChangeListener = CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->
        val checkedIndex : Int = buttonView.tag as Int

//        if(selectedGenreIndex!=0)
//        {
//            gAdapter.setCheckedState(selectedGenreIndex,false)
//        }

        selectedGenreIndex = checkedIndex
        gAdapter.setCheckedState(selectedGenreIndex,isChecked)

//        if(!isChecked)
//        {
//            selectedGenreIndex = 0
//            gAdapter.setCheckedState(0,true)
//
//        }
//        gAdapter.notifyDataSetChanged()

    }
}

genre_item.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">

    <data>

        <variable
            name="viewModel"
            type=".GenreObservable" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingTop="5dp"
        android:paddingBottom="5dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp">

        <CheckBox
            android:id="@+id/mdc_on_cb"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/category_selector"
            android:button="@null"
            android:checked="@={viewModel.genreChecked}"
            android:gravity="center"
            android:padding="10dp"
            android:tag="@{viewModel.genreId}"
            android:text="@{viewModel.genreName}"
            android:textColor="@color/category_selected_text_color"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

尽管我已经实现了两种方法OnCheckedChangeListener,但是我仍需要在viewmodel中添加databinding吗?如果没有,我应该在哪里实现逻辑?

0 个答案:

没有答案