NavigationView get / find en-tête disposition

171

Dans mon NavigationView, j'ai une disposition d'en-tête avec l'identifiant «viewId» avec des boutons actifs. Pour configurer ces boutons, je fais ce qui suit dans l'activité onPostCreate:

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

Avec la nouvelle version de la bibliothèque de support Android, ( 23.1.0 ), la vue est introuvable, elle renvoie null. Avec les versions précédentes, cela fonctionnait bien. Est-ce un bug ou est-ce que j'utilise cette fonctionnalité de manière incorrecte? Si tel est le cas, comment accéder à la disposition de l'en-tête et y ajouter un comportement?

khusrav
la source

Réponses:

429

La version 23.1.0 passe NavigationViewà l'utilisation de a RecyclerView(plutôt que la précédente ListView) et l'en-tête est ajouté comme l'un de ces éléments. Cela signifie qu'il n'est pas instantanément disponible pour appeler findViewById()- un laissez-passer de mise en page est nécessaire avant qu'il ne soit attaché au NavigationView.

Pour la version 23.1.1 de la bibliothèque de support, vous pouvez maintenant obtenir une référence à la vue d'en-tête en utilisant getHeaderView():

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

Cela a l'avantage de travailler sur des en-têtes ajoutés via XML et via du code.

Si vous utilisez toujours 23.1.0, conformément au bogue associé , vous pouvez gonfler l'en-tête dans le code et l'utiliser findViewById():

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

Jusqu'à ce que vous passiez à 23.1.1.

ianhanniballake
la source
1
Merci pour l'aide rapide, utilisera la solution de contournement. Avoir la méthode dédiée semble la voie à suivre, j'espère l'avoir dans les prochaines versions.
khusrav
2
@AlexanderFarber - le code que j'ai posté fonctionne de nouveau vers l'API 7
ianhanniballake
4
Je préfère rétrograder les bibliothèques. Introduire un bug, c'est comme une signature de Google. Si la nouvelle version a un bogue, Google a publié cette nouvelle version
BamsBamx
1
@GFPF - lorsque vous appelez inflateHeaderView, il attache la vue pour vous dans le bon calque dans le RecyclerViewavec le parent correct - ce que vous ne pouvez pas faire en externe NavigationView.
ianhanniballake
1
@RmK - merci, j'ai mis à jour pour répondre pour refléter les nouvelles API ajoutées dans 23.1.1 pour récupérer les en-têtes ajoutés via XML (car la solution de contournement précédente ne fonctionnait que sur les en-têtes ajoutés via le code).
ianhanniballake
142

Désormais, avec la version 23.1.1 de la bibliothèque de support de conception, vous pouvez utiliser

NavigationView navigationView = (NavigationView) findViewById(R.id.your_nav_view_id);
View header = navigationView.getHeaderView(0)
TextView text = (TextView) header.findViewById(R.id.textView);
François Dermu
la source
Vous pouvez également utiliser navigationView.getHeaderCount()si vous avez plus d'un en-tête pour une raison quelconque.
Francois Dermu
13

C'est comme ça que je l'ai fait en utilisant ButterKnifeet ça marche pour moi.

protected static class HeaderViewHolder {

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

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

puis utilisez ce support de vue comme ceci:

View header = navigationView.getHeaderView(0);
headerViewHolder = new HeaderViewHolder(header);
Wahib Ul Haq
la source
2
C'est parfait lorsque vous souhaitez supprimer la logique associée à View de votre activité. Bonne idée!
amouly le
2
Il fonctionne parfaitement avec ButterKnife, merci mon frère.
Rajesh Naddy
8

Pour moi, c'était la même situation avec 23.1.0, après la mise à jour, l'exception du pointeur nul est devenue. Dans ce cas, le NavigatorViewlook comme:

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

J'ai essayé la proposition de solution d'ianhanniballake mais cela ne fonctionne pas. Puis j'ai gonflé avec la phrase:

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

Après cela, je peux trouver par identifiant toutes les vues définies dans la nav_heardmise en page.

Campino
la source
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
la source
Bonjour et bienvenue sur Stack Overflow! Veuillez ajouter un texte expliquant comment cela résout la question posée ci-dessus. Merci!
Jonathan
0

Dans Kotlin @Francois Dermu, le code est comme

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

Version 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
la source