NavigationView get/find header layout
Asked Answered
N

10

184

In my NavigationView I have a header layout with id 'viewId' with active buttons. To setup those buttons, I do the following in activity's onPostCreate:

final View panel = findViewById(R.id.viewId);
panel.setOnClickListener(new View.OnClickListener() {
... setup goes here ...
});

With new version android support library, (23.1.0), the view can't be found, it returns null. With previous versions it worked well. Is it a bug or am I using this feature wrong? If so, how to access header layout and add behavior to it?

Noelyn answered 18/10, 2015 at 5:20 Comment(0)
H
456

Version 23.1.0 switches NavigationView to using a RecyclerView (rather than the previous ListView) and the header is added as one of those elements. This means it is not instantly available to call findViewById() - a layout pass is needed before it is attached to the NavigationView.

For version 23.1.1 of the Support Library, you can now get a reference to the header view using getHeaderView():

View headerLayout = navigationView.getHeaderView(0); // 0-index header

This has the advantage of working on headers added via XML and via code.

If you are still using 23.1.0, as per the related bug, you can inflate the header in code and use findViewById() on that:

View headerLayout = 
    navigationView.inflateHeaderView(R.layout.navigation_header);
panel = headerLayout.findViewById(R.id.viewId);
// panel won't be null

Until you move to 23.1.1.

Hade answered 18/10, 2015 at 5:57 Comment(10)
OnLayoutChangeListener requires min sdk level 11, but I have 9 in my app. Any ideas please, how to workaround findViewById returning null for NavigationView header?Maricruzmaridel
@AlexanderFarber - the code I posted works back to API 7Hade
I prefer to downgrade libs. Introducing a bug is like a signature from Google. If the new version has a bug, then Google released that new versionExudation
@GFPF - the accepted answer is strictly worse (inflate(R.layout.lay_header, null); will cause all layout_ attributes to be ignored, while this solution does not) and accomplishes the same result.Hade
@Hade This is true, but the method inflateHeaderView has not any overloading that consider set header view with "attachToRoot" true in method [inflate](developer.android.com/intl/pt-br/reference/android/view/…, android.view.ViewGroup, boolean)). How to solve it in the best way without ignoring the attributes?Wanderoo
@Wanderoo - when you call inflateHeaderView, it attaches the View for you in the correct layer in the RecyclerView with the correct parent - something that you cannot do externally to NavigationView.Hade
This method comes with the issue that if the header is already defined inside the xml file, calling inflateheader adds an extra header in the side drawer.Defensive
@Defensive - thanks, I've updated to answer to reflect the new APIs added in 23.1.1 to retrieve headers added via XML (as the previous workaround only worked on headers added via code).Hade
I really like how Google changes major part of view control in each and every sdk update, not.Lyric
getHeaderView(0).. i thought that the 0 the the index of the View but it's obvious that it is not, thanks.Watchword
T
152

Now with the 23.1.1 release of the design support library, you can use

NavigationView navigationView = (NavigationView) findViewById(R.id.your_nav_view_id);
View header = navigationView.getHeaderView(0)
TextView text = (TextView) header.findViewById(R.id.textView);
Typify answered 13/11, 2015 at 18:49 Comment(1)
You can also use navigationView.getHeaderCount() in case you have more than 1 header for whatever reason.Typify
G
14

This is how I did it using ButterKnife and it works for me.

protected static class HeaderViewHolder {

    @BindView(R.id.button)
    Button button;

    HeaderViewHolder(View view) {
        ButterKnife.bind(this, view);
    }
}

and then use this view holder like this :

View header = navigationView.getHeaderView(0);
headerViewHolder = new HeaderViewHolder(header);
Gardie answered 1/9, 2016 at 13:10 Comment(2)
This is perfect when you want to remove View related logic from your Activity. Great idea!Loy
Its working perfectly with ButterKnife,thanks brother.Mandalay
V
9

For me that was the same situation with 23.1.0, after of update the null pointer exception become. In this case the NavigatorView look like:

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

I tried the solution proposal by ianhanniballake but it does not work. Then I inflated with the sentence:

LayoutInflater.from(getContext()).inflate(R.layout.nav_header, mNavigationView);

After that, I can find by id all views defined in nav_heardlayout .

Volsci answered 28/10, 2015 at 21:41 Comment(0)
F
5
NavigationView navigationView = findViewById(R.id.your_nav_view);
View header = navigationView.getHeaderView(0);
TextView textUsername = header.findViewById(R.id.textView);
textUsername.setText("you text here ")
Forgot answered 19/3, 2019 at 14:27 Comment(0)
F
4
NavigationView navigationView = findViewById(R.id.your_nav_view);
View header = navigationView.getHeaderView(0);
TextView textUsername = header.findViewById(R.id.textView);
textUsername.setText("you text here ");
Forgot answered 19/3, 2019 at 14:33 Comment(1)
Hello and welcome to Stack Overflow! Please add some text explaining how this solves the question asked above. Thanks!Elver
C
1

In Kotlin @Francois Dermu code be like

val navigationView : NavigationView = findViewById(R.id.your_nav_view_id);
val header = navigationView.getHeaderView(0)
val textView = header.findViewById<TextView>(R.id.textView)
Carolinacaroline answered 19/11, 2019 at 22:35 Comment(0)
K
1

Kotlin version.

val navView: NavigationView = findViewById(R.id.nav_view)       
// set User Name
val headerView: View = navView.getHeaderView(0)
headerView.txtUserName.text = "User Name Goes here"
Kerenkeresan answered 23/1, 2020 at 10:58 Comment(0)
C
1

Works for me in java

   navigationView = findViewById(R.id.nav_view);
    View viewHeader = navigationView.getHeaderView(0);
    ((TextView)viewHeader.findViewById(R.id.tv_name)).setText(preferences.getString(MyConstant.NAME,"n/a"));
Concealment answered 26/9, 2022 at 5:3 Comment(0)
F
0

Here is how to change a username in a drawer.

NavigationView mNavigationView = findViewById(R.id.nav_view);
View mHeaderView = mNavigationView.getHeaderView(0);
TextView usernameTextview = mHeaderView.findViewById(R.id.drawer_email_textField);
Bundle b = getIntent().getExtras();
String username = b.getString("email");
usernameTextview.setText(username);

that's works for me

Feudalism answered 28/5, 2023 at 19:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.