How to get view from drawer header layout with binding in activity?

So this is my 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"
        tools:context="MainActivity"
    >
    <!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->
    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >

        <!-- As the main content view, the view below consumes the entire
             space available using match_parent in both dimensions. -->

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:id="@+id/ll_container"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">

                <android.support.v7.widget.Toolbar
                    android:id="@+id/my_awesome_toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@android:color/black"
                    android:fitsSystemWindows="true"
                    >

                    <TextView
                        android:id="@+id/toolbar_title"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="10dp"
                        android:layout_marginStart="10dp"
                        android:textColor="@android:color/white"
                        android:textSize="@dimen/abc_text_size_title_material_toolbar"
                        tools:text="@string/default_toolbar_title"/>

                </android.support.v7.widget.Toolbar>


                <FrameLayout
                    android:id="@+id/container"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent">

                </FrameLayout>
            </LinearLayout>

            <android.support.design.widget.FloatingActionButton
                android:id="@+id/fab_fuf"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_alignParentEnd="true"
                android:layout_alignParentRight="true"
                android:layout_marginBottom="20dp"
                android:layout_marginEnd="20dp"
                android:layout_marginRight="20dp"
                android:src="@drawable/flamme"
                app:fabSize="normal"
                />
        </RelativeLayout>

        <android.support.design.widget.NavigationView
            android:id="@+id/navigation_view"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:background="@android:color/black"
            **app:headerLayout="@layout/drawer_header"**
            app:itemTextColor="@color/drawer_item_color_selector"
            app:menu="@menu/menu_drawer"/>

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

and I am using binding for the activity so I don’t have to use the findViewById and cast it etc.. like this:

  • How can I change the OverScroll color in Android 2.3.1?
  • Can VideoView be detach and reattached without stopping the stream?
  • Sniffing an Android app to find API URL
  • Libgdx game crashes on Android
  • get text from pressed button
  • IP range of google GCM push notification server?
  • ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    
            Toolbar toolbar = binding.myAwesomeToolbar;
            toolbarTitle = binding.toolbarTitle;
            BalrogFontsHelper.SetKhandBoldToView(toolbarTitle);
            setSupportActionBar(toolbar);
            final ActionBar actionBar = getSupportActionBar();
            if (actionBar != null) {
                actionBar.setHomeAsUpIndicator(R.drawable.ic_dehaze_white_24);
                actionBar.setDisplayHomeAsUpEnabled(true);
                actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
                actionBar.setDisplayShowTitleEnabled(false);
            }
    
    
            drawerLayout = binding.drawerLayout;
            **tvLoggedUserEmail = (TextView) findViewById(R.id.tv_logged_user_email);**
            BalrogFontsHelper.SetKhandBoldToView(tvLoggedUserEmail);
    

    As you can see, I can get the views that are directly in the activity_main.xml layout by binding but when the view I am trying to get is not there I can’t see the variable in the binding object.

    drawer_header.xml:

        <?xml version="1.0" encoding="utf-8"?>
    
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    android:layout_width="match_parent"
                    android:layout_height="96dp"
                    xmlns:tools="http://schemas.android.com/tools"
                    android:background="@android:color/black"
                    android:theme="@style/ThemeOverlay.AppCompat.Dark">
    
    
        <TextView
            android:id="@+id/tv_logged_user_email"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="16dp"
            tools:text="@string/login_placeholder_email"
            android:textAllCaps="true"
            android:textAppearance="@style/TextAppearance.AppCompat.Body2"
            android:textSize="20sp"/>
    
    
    </RelativeLayout>
    

    How could I get this tv_logged_user_email TextView in a binding way so I have:

    **tvLoggedUserEmail = binding.tvLoggedUserEmail;**
    

  • android setting activity orientation by code
  • Can ViewPager have multiple views in per page?
  • Multiple super classes and code reuse
  • How to escape % in String.Format?
  • On logout, clear Activity history stack, preventing “back” button from opening logged-in-only Activites
  • Android limit time recording using intent
  • 11 Solutions collect form web for “How to get view from drawer header layout with binding in activity?”

    13/11/2015

    http://developer.android.com/tools/support-library/index.html

    update design support library 23.1.0 to 23.1.1

    Changes for Design Support library:
    Added the getHeaderView method to the NavigationView class.
    Fixed a transparent background issue for a FloatingActionButton object on devices running Android 4.0 (API level 15) and lower. (Issue 183315)

    ===================

    I don’t know why there is no method which providing header view
    attached by programmatically

    1.solution

    NavigationView navigationView = (NavigationView) findViewById(R.id.navigation);
    View headerView = navigationView.inflateHeaderView(R.layout.header_layout)
    ImageView iv = (ImageView)headerview.findViewById(...)
    

    2.solution

    NavigationView navigationView = (NavigationView) findViewById(R.id.navigation);
    View headerView = LayoutInflater.from(this).inflate(R.layout.header_layout, navigationView, false);
    navigationView.addHeaderView(view);
    
    ImageView iv = (ImageView) headerView.findViewById(...)
    

    I have/had the same problem.

    A workaround is to inflate the header view and add it programatically.

    Like this:

    DrawerHeaderBinding drawerHeaderBinding = DrawerHeaderBinding.inflate(LayoutInflater.from(navigationView.getContext()));
    navigationView.addHeaderView(drawerHeaderBinding.getRoot());
    drawerHeaderBinding.tvLoggedUserEmail = "email";
    drawerHeaderBinding.executePendingBindings();
    

    So remove the app:headerLayout and do it programatically. I do think google should fix the core issue here though, either in the design library or in the data binding library.

    I have a slightly cleaner solution, where I don’t have to “pollute” fragment/activity with code responsible for inflating and adding header view to NavigationView. I implemented extension class for NavigationView. I did that like this:

    Layout of my activity:

    <data>
        <variable
            name="dashboard"
            type="ramps.view.model.DashboardScreenViewModel"/>
    </data>
    
    <android.support.v4.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/activity_dashboard"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            bind:dashboard="@{dashboard}"
            />
    
        <android.support.design.widget.NavigationView
            android:id="@+id/nav_view"
            android:background="@color/white"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:fitsSystemWindows="true"
            app:navigationItemSelectedListener="@{dashboard.onMenuItemSelected}"
            app:model="@{dashboard.score}"
            app:menu="@menu/activity_main_drawer"/>
    
    </android.support.v4.widget.DrawerLayout>
    

    As you can see, there is no app:headerLayout in NavigationView, but I have added my custom app:model, with data I want to pass to the header layout.
    How did I define this custom parameter? By extension class:

    public class NavigationViewExtensions {
    
    @BindingAdapter({"bind:model"})
    public static void loadHeader(NavigationView view, ScoreViewModel model) {
        ViewNavigationHeaderBinding binding = ViewNavigationHeaderBinding.inflate(LayoutInflater.from(view.getContext()));
        binding.setScore(model);
        binding.executePendingBindings();
        view.addHeaderView(binding.getRoot());
      }
    }
    

    Just place this class anywhere in your project. And the layout of my header:

    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:bind="http://schemas.android.com/apk/res-auto"
    >
    
    <data>
    
        <import type="android.view.View"/>
    
        <variable
            name="score"
            type="ramps.view.model.ScoreViewModel"/>
    </data>
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/graphite"
        android:gravity="bottom"
        android:orientation="vertical"
        android:paddingBottom="@dimen/activity_vertical_margin_large"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin_large"
        android:theme="@style/ThemeOverlay.AppCompat.Dark">
    
        <include
            android:id="@+id/player_details_header_score"
            layout="@layout/view_avatar_score_header"
            bind:score="@{score}"/>
    
    </LinearLayout>
    

    ImageView imageView = (ImageView) navigationView.getHeaderView(0).findViewById(R.id.imageButton);
    
    imageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
    
            if (flag) {
                navigationView.getMenu().clear(); //clear old inflated items.
                navigationView.inflateMenu(R.menu.drawer_view1);
                flag = false;
            } else {
                navigationView.getMenu().clear(); //clear old inflated items.
                navigationView.inflateMenu(R.menu.drawer_view);
                flag = true;
            }
        }
    });
    

    If you set app:headerLayout="@layout/drawer_header then you don’t have to inflate the view again. You can just use .bind instead of .inflate.

    You can get the already inflated header view and bind it like this:

    View headerView = binding.navigationView.getHeaderView(0);
    DrawerHeaderBinding headerBinding = DrawerHeaderBinding.bind(headerView);
    

    Try this with DataBinding library it works for me.

    navigation_view_header.xml:

    <layout xmlns:android="http://schemas.android.com/apk/res/android">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/navigation_view_header_height"
        android:paddingLeft="@dimen/navigation_view_padding"
        android:paddingTop="@dimen/navigation_view_top_padding"
        android:background="@color/colorPrimary">
    
    
        <ImageView
            android:id="@+id/avatar"
            android:layout_width="@dimen/avatar_dimen"
            android:layout_height="@dimen/avatar_dimen"
            android:contentDescription="@null"
            android:src="@drawable/default_avatar" />
    
        <TextView
            android:id="@+id/profile_email"
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:layout_below="@+id/avatar"
            android:text="email"
            android:textColor="@color/white"
            android:layout_alignParentBottom="true"
            android:gravity="center_vertical" />
    
    </RelativeLayout>
    </layout>
    

    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="navigationItemSelectedListener"
                type="com.example.MainActivity"/>
        </data>
    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        android:tag="layout">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
    
            <android.support.v7.widget.Toolbar
                android:id="@+id/my_toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:titleTextColor="@color/white"
                android:background="@color/colorPrimary"
                app:theme="@style/Toolbar.Theme"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
    
            <FrameLayout
                android:id="@+id/fragment_container"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </LinearLayout>
    
        <android.support.design.widget.NavigationView
            android:id="@+id/navigation_view"
            android:layout_width="@dimen/navigation_view_width"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:fitsSystemWindows="true"
            app:theme="@style/Theme.AppCompat.Light"
            app:menu="@menu/drawer_menu"
            app:navigationItemSelectedListener="@{navigationItemSelectedListener::onNavigationItemSelected}"/>
    
    </android.support.v4.widget.DrawerLayout>
    </layout>
    

    and within your activity:

    ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this,
                    R.layout.activity_main);
    activityMainBinding.setNavigationItemSelectedListener(this);/* with this line navigation menu item selection events are handled in onNavigationItemSelected() specified in navigation_view_header.xml*/
    
    NavigationViewHeaderBinding navigationViewHeaderBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.navigation_view_header,activityMainBinding.navigationView,false);
            activityMainBinding.navigationView.addHeaderView(navigationViewHeaderBinding.getRoot());
    

    and make sure your activity implements NavigationView.OnNavigationItemSelectedListener

    Quite a simple solution here. Let’s suppose you added your NavigationView as

    <android.support.design.widget.NavigationView
        android:id="@+id/navigationView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_drawer_header"
        app:menu="@menu/menu_nav_drawer"/>
    

    And that you want to access a TextView in nav_drawer_header.xml that has an id of textView2. So you would just use this code in your activity:

    View headerContainer = navigationView.getHeaderView(0); // This returns the container layout in nav_drawer_header.xml (e.g., your RelativeLayout or LinearLayout)
    TextView textView2 = (TextView)headerContainer.findViewById(R.id.textView2);
    textView2.setText("Sorted!");
    

    No need to inflate or interfere with your existing code, etc.

    • Edit your gradle file to update com.android.support libraries to version 23.1.1 or beyond.

    • Use navigationView.getHeaderView(i), where i is the index of the headerview. If you just defined this view on layout, is 0.

    I have updated build tools from Android sdk manager, then 23.1.0 is also working fine for me.

    I am using buildToolsVersion "23.0.2" Before this it was 23.0.1.

    and there is no need of using:

    (View) navigationView.findViewById(R.id.idOfViewFromHeaderView);
    

    In your activity you can directly use:

    (View) findViewById(R.id.idOfViewFromHeaderView);
    

    It works for me.

    MainActivity.java:

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    
        NavHeaderMainBinding binding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.nav_header_main, navigationView, false);
    
        navigationView.addHeaderView(binding.getRoot());
    

    activity_main.xml:

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:openDrawer="start">
    
        <RelativeLayout
            android:id="@+id/content_frame"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <android.support.design.widget.AppBarLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
    
                <include layout="@layout/toolbar" />
    
            </android.support.design.widget.AppBarLayout>
    
        </RelativeLayout>
    
        <android.support.design.widget.NavigationView
            android:id="@+id/nav_view"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:fitsSystemWindows="true"
            app:menu="@menu/activity_main_drawer" />
    
    </android.support.v4.widget.DrawerLayout>
    

    nav_header.xml:

    <layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    
    <data>
    
        <variable
            name="account"
            type="lonja.dreamteam.su.trainingdiary.view_model.AccountViewModel"/>
    
    </data>
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/nav_header_height"
        android:background="@drawable/header_background"
        android:gravity="bottom"
        android:orientation="vertical"
        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">
    
        <de.hdodenhof.circleimageview.CircleImageView
            android:id="@+id/imageView"
            android:layout_width="72dp"
            android:layout_height="72dp"
            android:src="@{account.sex}"
            app:civ_border_color="@color/colorAccent"
            app:civ_border_width="0dp" />
    
        <TextView
            android:id="@+id/userName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingTop="@dimen/nav_header_vertical_spacing"
            android:text="@{account.name}"
            android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
    
    </LinearLayout>
    

    You can do this. First initialize the navigation view.

        NavigationView navigationView = (NavigationView) findViewById(R.id.navigation_view);
    

    and then initialize all the views that is inside of navigationView.

        CircleImageView circleView = (CircleImageView) navigationView.findViewById(R.id.circleView);
        TextView name = (TextView) navigationView.findViewById(R.id.name);
        TextView email = (TextView) navigationView.findViewById(R.id.email);
        LinearLayout header = (LinearLayout) navigationView.findViewById(R.id.header);
    

    and then you can use those views as you wish.
    eg:

            name.setText(NAME);
            email.setText(EMAIL);
    
    Android Babe is a Google Android Fan, All about Android Phones, Android Wear, Android Dev and Android Games Apps and so on.