NavigationView obtener / buscar diseño de encabezado

171

En mi NavigationView tengo un diseño de encabezado con ID 'viewId' con botones activos. Para configurar esos botones, hago lo siguiente en la actividad onPostCreate:

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

Con la nueva versión de la biblioteca de soporte de Android, ( 23.1.0 ), la vista no se puede encontrar, devuelve nulo. Con versiones anteriores funcionó bien. ¿Es un error o estoy usando mal esta función? Si es así, ¿cómo acceder al diseño del encabezado y agregarle comportamiento?

khusrav
fuente

Respuestas:

429

La versión 23.1.0 cambia NavigationViewa usar a RecyclerView(en lugar de la anterior ListView) y el encabezado se agrega como uno de esos elementos. Esto significa que no está disponible al instante para llamar findViewById(); se necesita un pase de diseño antes de adjuntarlo al NavigationView.

Para la versión 23.1.1 de la Biblioteca de soporte, ahora puede obtener una referencia a la vista de encabezado usando getHeaderView():

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

Esto tiene la ventaja de trabajar en encabezados agregados a través de XML y código.

Si todavía usa 23.1.0, según el error relacionado , puede inflar el encabezado en el código y usarlo findViewById()en eso:

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

Hasta que pases a 23.1.1.

ianhanniballake
fuente
1
Gracias por la pronta ayuda, utilizaremos la solución. Tener el método dedicado parece el camino a seguir, espero que lo tenga en futuras versiones.
khusrav
2
@AlexanderFarber: el código que publiqué funciona en API 7
ianhanniballake
44
Prefiero rebajar las bibliotecas. Introducir un error es como una firma de Google. Si la nueva versión tiene un error, Google lanzó esa nueva versión
BamsBamx
1
@GFPF: cuando llama inflateHeaderView, adjunta la Vista por usted en la capa correcta RecyclerViewcon el padre correcto, algo que no puede hacer externamente NavigationView.
ianhanniballake
1
@RmK: gracias, he actualizado para responder para reflejar las nuevas API agregadas en 23.1.1 para recuperar encabezados agregados a través de XML (ya que la solución anterior solo funcionaba en encabezados agregados a través de código).
ianhanniballake
142

Ahora con la versión 23.1.1 de la biblioteca de soporte de diseño, puede usar

NavigationView navigationView = (NavigationView) findViewById(R.id.your_nav_view_id);
View header = navigationView.getHeaderView(0)
TextView text = (TextView) header.findViewById(R.id.textView);
Francois Dermu
fuente
También puede usar navigationView.getHeaderCount()en caso de que tenga más de 1 encabezado por cualquier razón.
Francois Dermu
13

Así es como lo hice usando ButterKnifey funciona para mí.

protected static class HeaderViewHolder {

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

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

y luego use este soporte de vista de esta manera:

View header = navigationView.getHeaderView(0);
headerViewHolder = new HeaderViewHolder(header);
Wahib Ul Haq
fuente
2
Esto es perfecto cuando desea eliminar Ver lógica relacionada de su Actividad. ¡Gran idea!
amouly
2
Funciona perfectamente con ButterKnife, gracias hermano.
Rajesh Naddy
8

Para mí esa era la misma situación con 23.1.0, después de la actualización se convirtió en la excepción de puntero nulo. En este caso, el NavigatorViewaspecto es el siguiente:

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

Intenté la propuesta de solución de ianhanniballake pero no funciona. Luego inflé con la oración:

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

Después de eso, puedo encontrar por id todas las vistas definidas en el nav_hearddiseño.

Campino
fuente
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 ");
indrit saveta
fuente
¡Hola y bienvenido a Stack Overflow! Agregue un texto que explique cómo esto resuelve la pregunta que se hizo anteriormente. ¡Gracias!
Jonathan
0

En Kotlin, el código de @Francois Dermu será como

val navigationView : NavigationView = findViewById(R.id.your_nav_view_id);
val header = navigationView.getHeaderView(0)
val textView = header.findViewById<TextView>(R.id.textView)
Alex
fuente
0

Versión Kotlin.

val navView: NavigationView = findViewById(R.id.nav_view)       
// set User Name
val headerView: View = navView.getHeaderView(0)
headerView.txtUserName.text = "User Name Goes here"
Qadir Hussain
fuente