2

I'm trying to create custom tab control using android mvvm. The main goal is to be able to bind current selected section for example from recyclerView and set it on custom view. Custom control should read changes on bound property send it back when someone clicks other tab.

So far I decided to create custom view extending ViewGroup. View contains property representing currently selected position on tabs control. I bind those property to activity view model containing property of type(LiveData) which represents curently selected section on my recycler View. I include parts of my code.

This is the only tutorial I have found so far, but it really covers only simple usage of custom views.

My view:

<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>

<data>
    <variable
        name="viewModel"
        type="com.example.DeviceMainViewModel"/>
</data>

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.common.deviceMain.DeviceMainActivity">

    <com.example.ScreenToolbar
        android:id="@+id/toolbar_view"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        app:tabBackground="@drawable/main_tab_layout_bg"
        app:builtLayout="@{viewModel.toolbarList}"
        app:layoutRes="@layout/toolbar_device"
        app:layout_constraintEnd_toEndOf="parent"
        app:customPosition="@={viewModel.recyclerViewPosition}"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        android:onClick="@{viewModel::testButtonClick}"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/sectionRecyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        android:adapter="@{viewModel.adapter}"
        android:descendantFocusability="blocksDescendants"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/toolbar_view" />

</android.support.constraint.ConstraintLayout>

</layout>

Custom View:

class ScreenToolbar(context: Context, attributeSet: AttributeSet) :ViewGroup(context, attributeSet){

 var currentPosition: Int? = null
        set(value){
            field = value
            Log.d("ScrToolbar", "HIT!!!")
            //do rest of stuff to set curently selected tab
        }
...
}

Inside Activity viewmodel i have mutableLiveData

class DeviceMainViewModel @Inject constructor() : ViewModel() {
    val adapter = SectionsAdapter()
    val recyclerViewPosition : MutableLiveData<Int>
...
}

I expect that every time when i change LiveData in viewmodel, customView will react on that in setter of currentPosition. Also after adding onClickListener to customView I would like to make LiveData in activity viewModel to be modified. So far code does not build ("Cannot find getter for attribute app:currentPosition), but I think that whole approach is wrong.

PS. Additionally I dont know how to create bindingAdapters to MutableLiveData, and maybe this solution requires it.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115

0 Answers0