185

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?

0

10 Answers 10

455

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.

Sign up to request clarification or add additional context in comments.

10 Comments

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?
@AlexanderFarber - the code I posted works back to API 7
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 version
@GFPF - 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.
@RmK - 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).
|
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); 

1 Comment

You can also use navigationView.getHeaderCount() in case you have more than 1 header for whatever reason.
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); 

2 Comments

This is perfect when you want to remove View related logic from your Activity. Great idea!
Its working perfectly with ButterKnife,thanks brother.
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 .

Comments

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

Comments

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

1 Comment

Hello and welcome to Stack Overflow! Please add some text explaining how this solves the question asked above. Thanks!
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) 

Comments

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" 

Comments

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

Comments

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.