En Android, ¿cómo configurar la imagen del encabezado del cajón de navegación y el nombre mediante programación en el archivo de clase?

79

En android studio 1.4.1, he creado un nuevo proyecto de cajón de navegación que es predeterminado. Mi problema es que en este proyecto hay un archivo nav_header_main.xml que es para la imagen y el nombre del encabezado de navegación. Quiero que esta imagen y nombre se establezcan mediante programación en mi actividad de clase principal. Cómo hacer esto, lo intenté mucho, pero la aplicación falla.

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="[email protected]" />

</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;
    }
}
Kalai
fuente

Respuestas:

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

¡espero que esto ayude!

Triệu Đô La
fuente
2
navigationView.getHeaderView (0); ¿Por qué usamos 0 allí?
Lahiru Liyanage
51

Como se menciona en el error 190226 , desde la versión 23.1.0 que obtiene la vista de diseño de encabezado con: navigationView.findViewById(R.id.navigation_header_text)ya no funciona.

Una solución es inflar la vista del encabezado mediante programación y buscar la vista por ID en la vista del encabezado inflado.

Por ejemplo:

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

Idealmente debería haber un método, getHeaderView()pero ya se ha propuesto, veamos y esperemos a que se publique en la versión de funciones de la biblioteca de soporte de diseño.

Paresh Mayani
fuente
¿Puede decir cómo agregar la vista de texto y la vista de imagen también?
Kalai
1
Amigo, como se menciona en la respuesta, puede inflar el diseño del encabezado (con vista de imagen, vista de texto o cualquier vista que desee en el diseño del encabezado) usando el inflateHeaderView()método y puede encontrar la vista desde el mismo diseño inflado usandofindViewById()
Paresh Mayani
NavigationView navigationView = null; Ver headerView = navigationView.inflateHeaderView (R.layout.nav_header_main); TextView tv = (TextView) headerView.findViewById (R.id.textView); tv.setText ("comprobación"); Este es mi código aunque la aplicación falla
Kalai
11
está funcionando con el ejemplo dado y recuerde eliminar la línea android.support.design.widget.NavigationView app:headerLayout="@layout/nav_header_main"porque ya ha
inflado
El comentario de @milapTank ayudó ya que la vista del encabezado se inflaba dos veces hasta que eliminé la línea sugerida por él de mi XML.
Taimur Khan
25

no agregue encabezado en xml agregue usando código inflando el diseño

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
fuente
Sí, esto está obteniendo el resultado fácilmente, gracias bhai.
Sajid khan
7

En 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
fuente
6

Primero debe acceder al cajón de navegación en su MainActivity (o la actividad de llamadas) de esta manera:

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

Luego, debe eliminar el diseño del encabezado de activity_main.xml porque el diseño se inflará programáticamente en MainActivity. Su activity_main.xml debería verse así:

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

Luego, en su MainActivity, inflamos el diseño nav_header_main y obtenemos acceso a sus vistas, en este caso ImageView y 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);

Puedes leer más aquí

Ikhiloya Imokhai
fuente
5

Aquí está mi código a continuación funcionando perfectamente No agregue el encabezado en la etiqueta NavigationView en 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" />

agregue el encabezado mediante programación con el código siguiente

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.
fuente
no funcionó para mí, muestra nav_header vacío. (sin texto ni imagen)
maximus
@maximus Subiré el código en GitHub y podrás buscar el error que has cometido.
Anirudh R.Huilgol.
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);

            }

        }
    }

Espero que esto ayude.

Saurabh Singh
fuente
4
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"

Esto solucionará su problema <3

Mohammad Khair PK
fuente
2

EDITAR: funciona con la biblioteca de diseño hasta 23.0.1 pero no funciona en 23.1.0

En el diseño principal xml habrá NavigationViewdefinido, en ese uso app:headerLayoutpara configurar la vista del encabezado.

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

Y @layout/nav_drawer_headerserá el marcador de posición de la imagen y los textos.

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>

Y en su clase principal, puede controlar Imageviewy TextViewcomo de costumbre otras vistas.

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

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

Espero que esto ayude.

Kavin Prabhu
fuente
Lo he implementado y está funcionando sin problemas. Estoy usando esta forma desde hace bastante tiempo.
Kavin Prabhu
Lo uso en la biblioteca de diseño 22.2.1 y está funcionando bien. Nunca probé el 23.1.0
Kavin Prabhu
Lo intenté, pero la aplicación falla. El error de registro de gato se muestra cerca de navHeaderTitle.setText ("Nombre de aplicación")
kalai
¿Está utilizando la biblioteca de soporte 23.1.0? Si es así, mire el enlace proporcionado por @PareshMayani en el comentario anterior.
Kavin Prabhu
2

Sé que esta es una publicación antigua, pero estoy seguro de que esto podría ayudar a alguien en el futuro.

Simplemente puede obtener el elemento headerView de la vista de navegación haciendo esto:

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

Espero que esto ayude a alguien.

Ronnie
fuente
¿Cómo obtener TextView? seria mParent.findViewById()o solo findViewById()?
Si8
puede usar mView.findViewById (R.id.text_view);
Ronnie
2

También puede utilizar las funciones de Kotlinx

val hView = nav_view.getHeaderView(0)
hView.textViewName.text = "lorem ipsum"
hView.imageView.setImageResource(R.drawable.ic_menu_gallery)
Asignar
fuente
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);
                }
            });

He hecho este código por mí mismo con algo de lógica ... Está funcionando al 100% ... por favor, vota mis ans.

La vista de texto y la vista de imagen son de @ layout / nav_header_main.xml

Prajwal Waingankar
fuente
1

Es una publicación antigua, pero es nueva para mí. ¡Así que es sencillo! En esta parte del código:

 public boolean onNavigationItemSelected(MenuItem item) {

}, Enlacé un ImageView al LinearLayout, que contiene el ImageView del ejemplo, que se enumera a continuación. Importante: es el mismo código que obtienes cuando inicias un nuevo proyecto y eliges la plantilla "Actividad del cajón de navegación":

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

Di el LinearLayout y la ID, dentro de nav_header_main.xml (en mi caso, elegí 'navigation_header_container', así que fue así:

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

Nota: Tengo un ImageView ivCloseDrawer privado declarado en la parte superior, antes de onCreate (MainActivity).

¡Funcionó bien! Espero que te ayude, Saludos cordiales.

Heitor
fuente
1

Si usa fijaciones, puede hacerlo

val headerView = binding.navView.getHeaderView(0)
val headerBinding = NavDrawerHeaderBinding.bind(headerView)
headerBinding.textView.text = "Your text here"
carolino
fuente
0

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

Роман Бяков
fuente
1
Hola @ Роман Бяков, bienvenido a Stack Overflow. Gracias por tu aporte. ¿Sabe que la pregunta tiene más de 4 meses :-)? No estoy seguro de si la respuesta aún es necesaria ... Sin embargo, en diferentes respuestas, intente explicar un poco más. ¿Qué hay yourviewen su sugerencia y dónde debería poner el OP su código? ¿Debería agregar las líneas o reemplazar las mismas líneas con las suyas? Explicaciones como estas ayudarán a probar su respuesta y ver el valor de su contribución. Buena suerte.
peter_the_oak
Por lo que vale, no hay una respuesta definitiva a este problema y todavía está activo: ¿sabes que desde que pasó este plazo arbitrario de 4 meses, ha habido 3 nuevas publicaciones :-)? No estoy seguro de que su comentario sea necesario ... Sin embargo, en comentarios futuros, asegúrese de ceñirse a ayudar a mejorar las contribuciones, en lugar de desalentarlas por completo.
SQLiteNoob
Muchas preguntas que tienen más de 4 meses todavía obtienen respuesta. De hecho, ¡algunas preguntas que son MUCHO más antiguas (algunos AÑOS) todavía están recibiendo respuesta! Y eso es bueno. Aunque el OP puede haber obtenido su respuesta, hay personas que tienen la misma pregunta y para quienes la pregunta permanece sin respuesta con el conjunto de respuestas existente. Dado que StackOverflow desalienta la repetición de publicaciones de la misma pregunta, las nuevas respuestas ayudarán a otras personas con la misma pregunta. Además, las API cambian con el tiempo y las respuestas antiguas a veces contienen código que puede estar obsoleto.
ONE
0

Este es el método que puede usar para obtener la vista del encabezado y configurar los datos correctamente

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
fuente