简体   繁体   中英

How to Bind viewmodel to nested view in android

To bind my StaffViewModel data to StaffActivity view that has DrawerLayout and NavigationView . In that NavigationView there was a layout nav_header_staf that consist of staff name and email. How can i bind my viewmodel to that nav_header_staff to replace staff name and email

I have tried to bind the view model in both layout in activity_staff and nav_header_staff layout, but databinding doesn't work.

Here is what i have tried in my StaffActivity.kt

class StaffActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener, AnkoLogger {

    private var fragmentManager: FragmentManager = supportFragmentManager
    private lateinit var drawerLayout: DrawerLayout

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //Create View Model
        val staffBundle = intent.getBundleExtra(StaffModel.NAME)
        val staff = staffBundle.getSerializable(StaffModel.NAME) as StaffModel
        //Create databinding
        val staffViewModel = StaffViewModel(staff)
        val binding = DataBindingUtil.setContentView<ViewDataBinding>(this, R.layout.activity_staff)
        binding!!.setVariable(BR.staff, staffViewModel)

        val toolbar: Toolbar = toolbar
        setSupportActionBar(toolbar)

        val fab: FloatingActionButton = fab
        fab.setOnClickListener { view ->
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                .setAction("Action", null).show()
        }
        drawerLayout = drawer_layout
        val navView: NavigationView = nav_view

        val toggle = ActionBarDrawerToggle(
            this, drawerLayout, toolbar,
            R.string.navigation_drawer_open,
            R.string.navigation_drawer_close
        )
        drawerLayout.addDrawerListener(toggle)
        toggle.syncState()

        navView.setNavigationItemSelectedListener(this)
    }

and here is the activity_staff.xml layout

<layout>
    <data xmlns:android="http://schemas.android.com/apk/res/android">
        <variable name="staff" type="id.code.sakilarentaldvd.viewModel.StaffViewModel"/>
    </data>
    <androidx.drawerlayout.widget.DrawerLayout
            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"
            android:id="@+id/drawer_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            tools:openDrawer="start">


        <include
                layout="@layout/app_bar_staff"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>


        <com.google.android.material.navigation.NavigationView
                android:id="@+id/nav_view"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_gravity="start"
                android:fitsSystemWindows="true"
                app:headerLayout="@layout/nav_header_staff"
                app:menu="@menu/activity_staff_drawer"/>


    </androidx.drawerlayout.widget.DrawerLayout>
</layout>

and here is the nav_header_staff.xml layout

<?xml version="1.0" encoding="utf-8"?>
<layout>
    <data xmlns:android="http://schemas.android.com/apk/res/android">
        <variable name="staff" type="id.code.sakilarentaldvd.viewModel.StaffViewModel"/>
    </data>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:id="@+id/staffHeader"
        android:layout_height="@dimen/nav_header_height"
        xmlns:tools="http://schemas.android.com/tools"
        android:background="@drawable/side_nav_bar"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        android:theme="@style/ThemeOverlay.AppCompat.Dark"
        android:orientation="vertical"
        android:gravity="bottom">

    <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingTop="@dimen/nav_header_vertical_spacing"
            app:srcCompat="@mipmap/ic_launcher_round"
            android:contentDescription="@string/nav_header_desc"
            android:id="@+id/imageView"/>

    <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingTop="@dimen/nav_header_vertical_spacing"
            tools:text="username"
            android:text="@{staff.staffName}"
            android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>

    <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            tools:text="blabla@sakila.org"
            android:text="@{staff.email}"
            android:id="@+id/textView"/>

</LinearLayout>
</layout>

here is what the result does

在此处输入图片说明

Thank You stackoverflow, i know what i missed, here is my solution

what i change in StaffActivity.kt

class StaffActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener, AnkoLogger {

private var fragmentManager: FragmentManager = supportFragmentManager
private lateinit var drawerLayout: DrawerLayout

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    //Create View Model
    val staffBundle = intent.getBundleExtra(StaffModel.NAME)
    val staff = staffBundle.getSerializable(StaffModel.NAME) as StaffModel
    //Create databinding
    val staffViewModel = StaffViewModel(staff)
    //remove binding because no need to link view model with this layout
    setContentView(R.layout.activity_staff) // setActivityLayout

    ...

    // I override this object method
    val toggle =object: ActionBarDrawerToggle(
        this, drawerLayout, toolbar,
        R.string.navigation_drawer_open,
        R.string.navigation_drawer_close
    ){// do binding in this method
       override fun onDrawerStateChanged(newState: Int) {
            val binding2 = DataBindingUtil.bind<NavHeaderStaffBinding>(findViewById(R.id.staffHeader))
            binding2!!.staff= staffViewModel
            super.onDrawerStateChanged(newState)
        }
}
    drawerLayout.addDrawerListener(toggle)
    toggle.syncState()

    navView.setNavigationItemSelectedListener(this)
}

I made few changes in activity_staff.xml layout, by removing <layout> and <data> tags

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
        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"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:openDrawer="start">


    <include
            layout="@layout/app_bar_staff"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>


    <com.google.android.material.navigation.NavigationView
            android:id="@+id/nav_view"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:fitsSystemWindows="true"
            app:headerLayout="@layout/nav_header_staff"
            app:menu="@menu/activity_staff_drawer"/>


</androidx.drawerlayout.widget.DrawerLayout>

so this is the result

result

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM