Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Data Binding: Pass variable to NavigationView

When a user signs into my app and I receive their profile info (name, avatar, etc) in MainActivity, I'd like to populate some fields in my Navigation View Header with the user params via Data Binding. I've tried the method proposed in the docs, but maybe it is limited to <include /> only?

activity_main.xml

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

    <data>

        <variable
            name="user"
            type="com.example.app.models.User" />
    </data>

    <android.support.v4.widget.DrawerLayout 
        // layout params... >

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

        <android.support.design.widget.NavigationView xmlns:bind="http://schemas.android.com/apk/res-auto"
            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_main"
            app:menu="@menu/activity_main_drawer"
            bind:user="@{user}" />

    </android.support.v4.widget.DrawerLayout>
</layout>

nav_header_main.xml

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

<data>

    <variable
        name="user"
        type="com.example.app.models.User" />
</data>

<LinearLayout
    // layout params... >

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

</LinearLayout>
</layout>

MainActivity

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    binding.setUser(User.getInstance());
// other stuff...
}

I get 2 errors:

  1. error: cannot find symbol class ActivityMainBinding
  2. Cannot find the setter for attribute 'bind:user' with parameter type com.example.app.models.User on android.support.design.widget.NavigationView.

If I remove the bind:user line it builds, but it doesn't work of course. Any way to get this sort of thing to work?

like image 813
Kevin_TA Avatar asked Mar 27 '18 22:03

Kevin_TA


Video Answer


1 Answers

This worked for me:

activity_main.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"
        xmlns:tools="http://schemas.android.com/tools">

    <androidx.drawerlayout.widget.DrawerLayout
            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_main"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

        <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_main"
                app:menu="@menu/activity_main_drawer"/>

    </androidx.drawerlayout.widget.DrawerLayout>

</layout>

nav_header_main.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"
        android:id="@+id/layout_nav_view_header">

    <data>
        <variable
                name="user"
                type="com.myapp.model.UserSettings"/>
    </data>

    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/nav_header_height"
            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"
                android:text="@{user.name}"
                android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>

        <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/nav_header_subtitle"
                android:id="@+id/textView"/>

    </LinearLayout>

</layout>

And then in the activity's onCreate:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val viewHeader = nav_view.getHeaderView(0)
    val navViewHeaderBinding : NavHeaderMainBinding = NavHeaderMainBinding.bind(viewHeader)
    navViewHeaderBinding.user = UserSettings(null, null, "John Doe", "Android Developer", null)
}
like image 121
Johann Avatar answered Sep 18 '22 09:09

Johann