NavigationView Header-Layout abrufen / finden


171

In meiner Navigationsansicht habe ich ein Header-Layout mit der ID 'viewId' mit aktiven Schaltflächen. Um diese Schaltflächen einzurichten, gehe ich in den Aktivitäten wie folgt vor onPostCreate:

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

Mit der Android-Unterstützungsbibliothek der neuen Version ( 23.1.0 ) kann die Ansicht nicht gefunden werden und gibt null zurück. Mit früheren Versionen hat es gut funktioniert. Ist es ein Fehler oder verwende ich diese Funktion falsch? Wenn ja, wie kann man auf das Header-Layout zugreifen und ihm Verhalten hinzufügen?

Antworten:


429

In Version 23.1.0 NavigationViewwird ein RecyclerView(anstelle des vorherigen ListView) verwendet, und der Header wird als eines dieser Elemente hinzugefügt. Dies bedeutet, dass es nicht sofort zum Anrufen verfügbar ist findViewById()- ein Layout-Pass ist erforderlich, bevor er an das angehängt wird NavigationView.

Für Version 23.1.1 der Support-Bibliothek können Sie jetzt einen Verweis auf die Header-Ansicht abrufen , indem Sie getHeaderView():

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

Dies hat den Vorteil, dass Header bearbeitet werden, die über XML und Code hinzugefügt wurden.

Wenn Sie gemäß dem zugehörigen Fehler immer noch 23.1.0 verwenden, können Sie den Header im Code aufblasen und Folgendes verwenden findViewById():

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

Bis Sie zu 23.1.1 wechseln.


1
Vielen Dank für die schnelle Hilfe, wird die Problemumgehung verwenden. Die dedizierte Methode scheint der richtige Weg zu sein, die Hoffnung wird es in zukünftigen Versionen geben.
Khusrav

2
@ AlexanderFarber - der Code, den ich gepostet habe, funktioniert zurück zu API 7
ianhanniballake

4
Ich ziehe es vor, Bibliotheken herunterzustufen. Das Einführen eines Fehlers ist wie eine Signatur von Google. Wenn die neue Version einen Fehler hat, hat Google diese neue Version veröffentlicht
BamsBamx

1
@GFPF - Wenn Sie aufrufen inflateHeaderView, wird die Ansicht für Sie in der richtigen Ebene RecyclerViewmit dem richtigen übergeordneten Element angehängt - etwas, das Sie extern nicht tun können NavigationView.
Ianhanniballake

1
@RmK - danke, ich habe aktualisiert, um die neuen APIs zu berücksichtigen, die in 23.1.1 hinzugefügt wurden, um über XML hinzugefügte Header abzurufen (da die vorherige Problemumgehung nur mit über Code hinzugefügten Headern funktioniert hat).
Ianhanniballake

142

Mit der Version 23.1.1 der Design-Support-Bibliothek können Sie jetzt verwenden

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

Sie können auch verwenden, navigationView.getHeaderCount()wenn Sie aus irgendeinem Grund mehr als einen Header haben.
Francois Dermu

13

So habe ich es gemacht ButterKnifeund es funktioniert für mich.

protected static class HeaderViewHolder {

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

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

und verwenden Sie dann diesen Ansichtshalter wie folgt:

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

2
Dies ist perfekt, wenn Sie die View-bezogene Logik aus Ihrer Aktivität entfernen möchten. Großartige Idee!
Amouly

2
Es funktioniert perfekt mit ButterKnife, danke Bruder.
Rajesh Naddy

8

Für mich war das die gleiche Situation mit 23.1.0, nach dem Update wird die Nullzeiger-Ausnahme. In diesem Fall NavigatorViewsieht das so aus:

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

Ich habe den Lösungsvorschlag von ianhanniballake ausprobiert, aber er funktioniert nicht. Dann habe ich mit dem Satz aufgeblasen:

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

Danach kann ich anhand der ID alle im nav_heardLayout definierten Ansichten finden .


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

Hallo und willkommen bei Stack Overflow! Bitte fügen Sie einen Text hinzu, der erklärt, wie dies die oben gestellte Frage löst. Vielen Dank!
Jonathan

0

In Kotlin @Francois Dermu Code sei wie

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

0

Kotlin-Version.

val navView: NavigationView = findViewById(R.id.nav_view)       
// set User Name
val headerView: View = navView.getHeaderView(0)
headerView.txtUserName.text = "User Name Goes here"
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.