NavigationView ottieni / trova layout intestazione


171

Nel mio NavigationView ho un layout di intestazione con ID 'viewId' con pulsanti attivi. Per impostare quei pulsanti, eseguo le seguenti attività onPostCreate:

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

Con la nuova versione della libreria di supporto Android, ( 23.1.0 ), la vista non può essere trovata, restituisce null. Con le versioni precedenti ha funzionato bene. È un bug o sto usando questa funzione in modo errato? In tal caso, come accedere al layout dell'intestazione e aggiungere comportamento ad esso?

Risposte:


429

La versione 23.1.0 passa NavigationViewall'uso di un RecyclerView(anziché del precedente ListView) e l'intestazione viene aggiunta come uno di quegli elementi. Ciò significa che non è immediatamente disponibile per la chiamata findViewById(): è necessario un passaggio di layout prima di essere collegato a NavigationView.

Per la versione 23.1.1 della libreria di supporto, ora puoi ottenere un riferimento alla vista dell'intestazione usando getHeaderView():

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

Questo ha il vantaggio di lavorare su intestazioni aggiunte via XML e via codice.

Se stai ancora usando 23.1.0, come per il relativo bug , puoi gonfiare l'intestazione nel codice e usarla findViewById()su:

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

Fino a quando non si passa a 23.1.1.


1
Grazie per l'aiuto rapido, utilizzerà la soluzione alternativa. Avere il metodo dedicato sembra la strada da percorrere, la speranza lo avrà nelle versioni future.
Khusrav,

2
@AlexanderFarber - il codice che ho pubblicato funziona su API 7
ianhanniballake,

4
Preferisco effettuare il downgrade delle librerie. Introdurre un bug è come una firma di Google. Se la nuova versione ha un bug, Google ha rilasciato quella nuova versione
BamsBamx,

1
@GFPF - quando chiami inflateHeaderView, collega la vista per te nel livello corretto nel RecyclerViewcon il genitore corretto - qualcosa a cui non puoi fare esternamente NavigationView.
ianhanniballake,

1
@RmK - grazie, ho aggiornato per rispondere in modo da riflettere le nuove API aggiunte in 23.1.1 per recuperare le intestazioni aggiunte tramite XML (poiché la soluzione precedente funzionava solo sulle intestazioni aggiunte tramite codice).
ianhanniballake,

142

Ora con la versione 23.1.1 della libreria di supporto alla progettazione, è possibile utilizzare

NavigationView navigationView = (NavigationView) findViewById(R.id.your_nav_view_id);
View header = navigationView.getHeaderView(0)
TextView text = (TextView) header.findViewById(R.id.textView);

Puoi anche utilizzare navigationView.getHeaderCount()nel caso in cui tu abbia più di 1 intestazione per qualsiasi motivo.
Francois Dermu,

13

È così che l'ho fatto usando ButterKnifee funziona per me.

protected static class HeaderViewHolder {

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

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

e quindi usa questo supporto vista in questo modo:

View header = navigationView.getHeaderView(0);
headerViewHolder = new HeaderViewHolder(header);

2
Questo è perfetto quando si desidera rimuovere Visualizza la logica correlata dalla propria attività. Grande idea!
amouly

2
Funziona perfettamente con ButterKnife, grazie fratello.
Rajesh Naddy,

8

Per me quella era la stessa situazione con 23.1.0, dopo l'aggiornamento diventa l'eccezione puntatore null. In questo caso NavigatorViewsembra che:

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

Ho provato la proposta di soluzione di ianhanniballake ma non funziona. Poi ho gonfiato con la frase:

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

Successivamente, posso trovare per id tutte le viste definite nel nav_heardlayout.


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

Ciao e benvenuto su Stack Overflow! Si prega di aggiungere un testo che spiega come questo risolve la domanda posta sopra. Grazie!
Jonathan

0

In Kotlin @Francois il codice Dermu è simile

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

0

Versione di 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"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.