83

In android studio 1.4.1, I have created new Navigation Drawer Project which is default.My issue is in this project there is nav_header_main.xml file which is for navigation header image and name. I want this image and name should be set programmatically in my main class activity. How to do this, I tried lot but the app crashes.

nav_header_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout        
android:layout_width="match_parent"
android:id="@+id/headerView"
android:layout_height="@dimen/nav_header_height"
android:background="@drawable/side_nav_bar"
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">

<ImageView
    android:id="@+id/imageView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingTop="@dimen/nav_header_vertical_spacing"
    android:src="@android:drawable/sym_def_app_icon" />

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="@dimen/nav_header_vertical_spacing"
    android:text="Android Studio"
    android:textAppearance="@style/TextAppearance.AppCompat.Body1" />

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="android.studio@android.com" />

</LinearLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout            

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

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

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

MainActivity.Class

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.NavigationView;
import android.support.design.widget.Snackbar;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        LinearLayout headerImageView= (LinearLayout) findViewById(R.id.headerView);


        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            Toast.makeText(getApplicationContext(),"working",Toast.LENGTH_LONG).show();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_camara) {
            // Handle the camera action
        } else if (id == R.id.nav_gallery) {

        } else if (id == R.id.nav_slideshow) {

        } else if (id == R.id.nav_manage) {

        } else if (id == R.id.nav_share) {

        } else if (id == R.id.nav_send) {

        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);

        return true;
    }
}
Paresh Mayani
  • 127,700
  • 71
  • 241
  • 295
kalai
  • 839
  • 1
  • 7
  • 5

17 Answers17

246
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
View hView = navigationView.getHeaderView(0);
TextView nav_user = (TextView) hView.findViewById(R.id.nav_name);
nav_user.setText(user);
Ryan M
  • 18,333
  • 31
  • 67
  • 74
Triệu Đô La
  • 2,471
  • 1
  • 9
  • 6
52

As mentioned in the bug 190226, Since version 23.1.0 getting header layout view with: navigationView.findViewById(R.id.navigation_header_text) no longer works.

A workaround is to inflate the headerview programatically and find view by ID from the inflated header view.

For example:

View headerView = navigationView.inflateHeaderView(R.layout.navigation_header);
headerView.findViewById(R.id.navigation_header_text);

Ideally there should be a method getHeaderView() but it has already been proposed, let's see and wait for it to be released in the feature release of design support library.

Paresh Mayani
  • 127,700
  • 71
  • 241
  • 295
  • Can you please say how to add text view and image view also – kalai Nov 06 '15 at 06:32
  • 1
    Dude, as mentioned in the answer you can inflate the header layout (with imageview, textview or whatever views you want in header layout) using `inflateHeaderView()` method and can find view from the same inflated layout using `findViewById()` – Paresh Mayani Nov 06 '15 at 06:34
  • NavigationView navigationView = null; View headerView = navigationView.inflateHeaderView(R.layout.nav_header_main); TextView tv=(TextView)headerView.findViewById(R.id.textView); tv.setText("checking"); This my code eventhough app crashes – kalai Nov 06 '15 at 07:46
  • 11
    its working with given example and remember remove line from `android.support.design.widget.NavigationView` `app:headerLayout="@layout/nav_header_main"` because you have already inflate programmatically – MilapTank Feb 10 '16 at 12:12
  • @milapTank comment helped as the header view was inflating twice until I removed suggested line by him from my XML. – Taimur Hassan May 04 '16 at 11:19
  • In version 23.4.0 this bug is still present. – The Berga May 16 '16 at 11:52
28

don't add header in xml add using code by inflating layout

View hView =  navigationView.inflateHeaderView(R.layout.nav_header_main);
ImageView imgvw = (ImageView)hView.findViewById(R.id.imageView);
TextView tv = (TextView)hView.findViewById(R.id.textview);
imgvw .setImageResource();
tv.settext("new text");
Ashish Agrawal
  • 1,977
  • 2
  • 18
  • 32
7

In Kotlin

    val hView = nav_view.getHeaderView(0)
    val textViewName = hView.findViewById(R.id.textViewName) as TextView
    val textViewEmail = hView.findViewById(R.id.textViewEmail) as TextView
    val imgvw = hView.findViewById(R.id.imageView) as ImageView
    imgvw.setImageResource(R.drawable.ic_menu_gallery)
Naveed Ahmad
  • 6,627
  • 2
  • 58
  • 83
6

First you need to access the navigation drawer in your MainActivity(or the calling activity) like this:

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

Then you need to remove the header layout from the activity_main.xml because the layout will be inflated programatically in the MainActivity. Your activity_main.xml should look like this:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout            

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

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

Then in your MainActivity, we inflate the nav_header_main layout and get access to its views, in this case the ImageView and TextView

//inflate header layout
View navView =  navigationView.inflateHeaderView(R.layout.nav_header_main);
//reference to views
ImageView imgvw = (ImageView)navView.findViewById(R.id.imageView);
TextView tv = (TextView)navView.findViewById(R.id.textview);
//set views
imgvw.setImageResource(R.drawable.your_image);
tv.setText("new text");

navigationView.setNavigationItemSelectedListener(this);

You can read more here

Ikhiloya Imokhai
  • 152
  • 3
  • 13
5

Here is my code below perfectly working Do not add the header in NavigationView tag in activity_main.xml

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

<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"
    app:itemBackground="@drawable/active_drawer_color" />

add header programmatically with below code

View navHeaderView = navigationView.inflateHeaderView(R.layout.nav_header_main);
    headerUserName = (TextView) navHeaderView.findViewById(R.id.nav_header_username);
    headerMobileNo = (TextView) navHeaderView.findViewById(R.id.nav_header_mobile);
    headerMobileNo.setText("+918861899697");
    headerUserName.setText("Anirudh R Huilgol");
Anirudh R.Huilgol.
  • 839
  • 1
  • 15
  • 16
5
val navigationView: NavigationView =  findViewById(R.id.nv)
val header: View = navigationView.getHeaderView(0)
val tv: TextView = header.findViewById(R.id.profilename)
tv.text = "Your_Text"

This will fix your problem <3

blueware
  • 5,205
  • 1
  • 40
  • 60
Mohammad Khair
  • 436
  • 6
  • 15
4
  nav = ( NavigationView ) findViewById( R.id.navigation );

    if( nav != null ){
        LinearLayout mParent = ( LinearLayout ) nav.getHeaderView( 0 );

        if( mParent != null ){
            // Set your values to the image and text view by declaring and setting as you need to here.

            SharedPreferences prefs = getSharedPreferences("user_data", MODE_PRIVATE);
            String photoUrl = prefs.getString("photo_url", null);
            String user_name = prefs.getString("name", "User");

            if(photoUrl!=null) {
                Log.e("Photo Url: ", photoUrl);

                TextView userName = mParent.findViewById(R.id.user_name);
                userName.setText(user_name);

                ImageView user_imageView = mParent.findViewById(R.id.avatar);

                RequestOptions requestOptions = new RequestOptions();
                requestOptions.placeholder(R.drawable.ic_user_24dp);
                requestOptions.error(R.drawable.ic_user_24dp);

                Glide.with(this).load(photoUrl)
                        .apply(requestOptions).thumbnail(0.5f).into(user_imageView);

            }

        }
    }

Hope this helps.

Saurabh Singh
  • 1,241
  • 13
  • 11
3

If you're using bindings you can do

val headerView = binding.navView.getHeaderView(0)
val headerBinding = NavDrawerHeaderBinding.bind(headerView)
headerBinding.textView.text = "Your text here"
Caroline
  • 31
  • 3
2

EDIT : Works with design library upto 23.0.1 but doesn't work on 23.1.0

In main layout xml you will have NavigationView defined, in that use app:headerLayout to set the header view.

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

And the @layout/nav_drawer_header will be the place holder of the image and texts.

nav_drawer_header.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="170dp"
android:orientation="vertical">

<RelativeLayout
    android:id="@+id/headerRelativeLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scaleType="fitXY"
        android:src="@drawable/background" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/action_bar_size"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:background="#40000000"
        android:gravity="center"
        android:orientation="horizontal"
        android:paddingBottom="5dp"
        android:paddingLeft="16dp"
        android:paddingRight="10dp"
        android:paddingTop="5dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginLeft="35dp"
            android:orientation="vertical"
            android:weightSum="2">


            <TextView
                android:id="@+id/navHeaderTitle"
                android:layout_width="wrap_content"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:textColor="@android:color/white" />

            <TextView
                android:id="@+id/navHeaderSubTitle"
                android:layout_width="wrap_content"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:textAppearance="?android:attr/textAppearanceSmall"
                android:textColor="@android:color/white" />

        </LinearLayout>

    </LinearLayout>
</RelativeLayout>
</LinearLayout>

And in your main class, you can take handle of Imageview and TextView as like normal other views.

TextView navHeaderTitle = (TextView) findViewById(R.id.navHeaderTitle);
navHeaderTitle.setText("Application Name");

TextView navHeaderSubTitle = (TextView) findViewById(R.id.navHeaderSubTitle);
navHeaderSubTitle.setText("Application Caption");

Hope this helps.

Kavin Prabhu
  • 2,307
  • 2
  • 17
  • 36
2

NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); navigationView.addHeaderView(yourview);

rbyakov
  • 21
  • 2
  • 2
    Hi @Роман Бяков, welcome to Stack Overflow. Thanks for your contribution. Are you aware that the question is more than 4 months old :-) ? Not sure if the answer still is needed... However, on different answers, try to explain a little bit more. What is `yourview` in your suggestion, and where should the OP put your code? Should she/he *add* the lines or *replace* same lines with yours? Explanations like these will help to try your answer and to see the value of your contribution. Good luck. – peter_the_oak Mar 17 '16 at 11:29
  • For what it's worth, there is no definitive answer to this problem and it is still active: are you aware that since this arbitrary 4 month deadline has passed, there have been 3 new posts :-)? Not sure your comment is needed... However, on future comments, be sure to stick to helping improve contributions, instead of discouraging them altogether. – SQLiteNoob May 23 '17 at 03:22
  • Lots of questions that are older than 4 months old still get answers. In fact, some questions that are MUCH older (some YEARS old) are still getting answers! And that's a good thing. Although the OP may have gotten his answer, there are people who have the same question and for whom the question remains unanswered with the existing pool of answers. Since StackOverflow discourages re-posts of the same question, new answers will help other people with the same question. Moreover, APIs change over time and old answers sometimes contain code that may be deprecated. – ONE Jun 19 '17 at 08:26
2

I know this is an old post but i am sure that this might help someone down the road.

You can simply get the headerView element of the Navigation view by doing this:

 NavigationView mView = ( NavigationView ) findViewById( R.id.nav_view );

 if( mView != null ){
     LinearLayout mParent = ( LinearLayout ) mView.getHeaderView( 0 );

     if( mParent != null ){
        // Set your values to the image and text view by declaring and setting as you need to here. 
     }
 }

I hope that this helps someone.

Ronnie
  • 239
  • 2
  • 9
2

Also you can use Kotlinx features

val hView = nav_view.getHeaderView(0)
hView.textViewName.text = "lorem ipsum"
hView.imageView.setImageResource(R.drawable.ic_menu_gallery)
Mete
  • 2,805
  • 1
  • 28
  • 38
2
   FirebaseAuth firebaseauth = FirebaseAuth.getInstance(); 

   NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);   //displays text of header of nav drawer.
    View headerview = navigationView.getHeaderView(0);

    TextView tt1 = (TextView) headerview.findViewById(R.id.textview_username);
    tt1.setText(firebaseauth.getCurrentUser().getDisplayName());//username of logged in user.  

   TextView tt = (TextView) headerview.findViewById(R.id.textView_emailid);
    tt.setText(firebaseauth.getCurrentUser().getEmail());    //email id of logged in user.

    final ImageView img1 = (ImageView) headerview.findViewById(R.id.imageView_userimage);
    Glide.with(getApplicationContext())
            .load(firebaseauth.getCurrentUser().getPhotoUrl()).asBitmap().atMost().error(R.drawable.ic_selfie_point_icon)   //asbitmap after load always.
            .into(new SimpleTarget<Bitmap>() {
                @Override
                public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                    img1.setImageBitmap(resource);
                }
            });

I have made this code by myself with some logic...Its 100% working.....pls do upvote my ans.

The textview and imageview are from @layout/nav_header_main.xml

Prajwal Waingankar
  • 2,534
  • 2
  • 13
  • 20
1

It's and old post, but it's new for me. So, it is straight forward! In this part of the code:

 public boolean onNavigationItemSelected(MenuItem item) {

} , I bound an ImageView to the LinearLayout, which contains the ImageView from the example, listed below. Mind: it's the same code you get when you start a new project, and choose the template "Navigation Drawer Activity":

<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:src="@android:drawable/sym_def_app_icon" />

I gave the LinearLayout and ID, inside nav_header_main.xml (in my case I chose 'navigation_header_container' , so it went this way:

LinearLayout lV = (LinearLayout) findViewById(R.id.navigation_header_container);

    ivCloseDrawer = (ImageView) lV.findViewById(R.id.imageView);
    ivCloseDrawer.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            drawer.closeDrawer(GravityCompat.START);
        }
    });

Note: I have a private ImageView ivCloseDrawer declared at the top, before onCreate (MainActivity).

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Heitor
  • 11
  • 4
0

Here is the method you can use to get header view and set data accourdingly

val headerView: View? = navigationView.getHeaderView(0) // Index of the added headerView  

// Now you can access child views of the header view
val titleTextView: TextView? = headerView?.findViewById(R.id.titleTextView)
Sumit Jain
  • 1,100
  • 1
  • 14
  • 27
0

For those who use KOTLIN :

val headerview = binding.navDrawer.getHeaderView(0)
val NavDrawheaderviewRef = NavdrawerHeaderLayoutBinding.bind(headerview)

NavDrawheaderviewRef.btnSearch.setOnClickListener
{
Toast.make(this , "Hii buddy",LENGTH_SHORT).show()    
    }

Here :

  • navDrawer = id of my Navigation Drawer
  • NavdrawerHeaderLayoutBinding = a func which is used to get a ref of header layout.
  • btnSearch = a button present in the header layout
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Sumit
  • 529
  • 5
  • 13