如何在Android中将ViewModel绑定到嵌套视图

时间:2019-08-13 03:54:15

标签: android android-layout kotlin mvvm data-binding

大家好,

我正在尝试实施MVVM概念。

我在将StaffViewModel数据绑定到具有StaffActivityDrawerLayout的{​​{1}}视图时遇到问题。在NavigationView中,存在一个布局NavigationView,该布局由员工姓名和电子邮件组成。如何将我的视图模型绑定到该nav_header_staf上以替换工作人员姓名和电子邮件

我尝试将视图模型绑定到nav_header_staffactivity_staff布局中,但是nav_header_staff不起作用。

这是我在StaffActivity.kt中尝试过的内容

databinding

,这是activity_staff.xml布局

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)
    }

这是nav_header_staff.xml布局

<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>

这是结果的作用

enter image description here

1 个答案:

答案 0 :(得分:0)

感谢您stackoverflow,我知道我错过了什么,这是我的解决方案

我在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)
}

我通过删除activity_staff.xml<layout>标签对<data>布局进行了几处更改

<?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>

所以这就是结果

result