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

╄→尐↘猪︶ㄣ 提交于 2019-11-27 05:48:24

问题


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:

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

回答1:


Updated solution (13/11/2015)

Solution: Update your Design Support Library to 23.1.1:

Changes for Design Support library 23.1.1:

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

See https://developer.android.com/tools/support-library/index.html for more info


Original solution

I don't know why there is no method which provides header view attached programmatically.

Instead, here's two solutions:

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

Or:

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

ImageView iv = (ImageView) headerView.findViewById(R.id.yourImageView)



回答2:


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>




回答3:


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



回答4:


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.




回答5:


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



回答6:


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/my_nav_drawer_header"
    app:menu="@menu/menu_nav_drawer"/>

And that you want to access a TextView in my_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 from your navigation drawer header layout file (e.g., the parent RelativeLayout/LinearLayout in your my_nav_drawer_header.xml file)
TextView textView2 = (TextView)headerContainer.findViewById(R.id.textView2);
textView2.setText("Sorted!");

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




回答7:


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




回答8:


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




回答9:


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



回答10:


Just put navigationView.getHeaderView(0) then use any views

        TextView profile,info;
        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        profile = navigationView.getHeaderView(0).findViewById(R.id.profile);
        info = navigationView.getHeaderView(0).findViewById(R.id.info);
        profile.setOnClickListener(this);
        info.setOnClickListener(this);



回答11:


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>




回答12:


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


来源:https://stackoverflow.com/questions/32246360/how-to-get-view-from-drawer-header-layout-with-binding-in-activity

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!