Wie kann man in Android das Header-Bild und den Namen der Navigationsschublade programmgesteuert in der Klassendatei festlegen?

77

In Android Studio 1.4.1 habe ich ein neues Navigations-Schubladen-Projekt erstellt, das standardmäßig verwendet wird. Mein Problem ist, dass in diesem Projekt die Datei nav_header_main.xml für das Bild und den Namen des Navigations-Headers enthalten ist. Ich möchte, dass dieses Bild und dieser Name programmgesteuert in meiner Hauptklassenaktivität festgelegt werden. Wie das geht, habe ich viel versucht, aber die App stürzt ab.

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
quelle

Antworten:

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

Ich hoffe das hilft!

Triệu Đô La
quelle
2
navigationView.getHeaderView (0); Warum verwenden wir dort 0?
Lahiru Liyanage
51

Wie im Fehler 190226 erwähnt , funktioniert das Abrufen der Header-Layout-Ansicht seit Version 23.1.0 navigationView.findViewById(R.id.navigation_header_text)nicht mehr.

Eine Problemumgehung besteht darin, die Kopfansicht programmgesteuert aufzublasen und die Ansicht anhand der ID in der aufgeblasenen Kopfansicht zu suchen.

Zum Beispiel:

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

Idealerweise sollte es eine Methode geben, die getHeaderView()jedoch bereits vorgeschlagen wurde. Lassen Sie uns sehen und warten, bis sie in der Feature-Version der Design-Support-Bibliothek veröffentlicht wird.

Paresh Mayani
quelle
Können Sie bitte sagen, wie man
Textansicht
1
Alter, wie in der Antwort erwähnt, können Sie das Header-Layout (mit Bildansicht, Textansicht oder beliebigen Ansichten im Header-Layout) mithilfe der inflateHeaderView()Methode aufblasen und die Ansicht aus demselben aufgeblasenen Layout mithilfe vonfindViewById()
Paresh Mayani
NavigationView navigationView = null; View headerView = navigationView.inflateHeaderView (R.layout.nav_header_main); TextView tv = (TextView) headerView.findViewById (R.id.textView); tv.setText ("Prüfen"); Dies ist mein Code, obwohl die App abstürzt
Kalai
11
Es funktioniert mit dem angegebenen Beispiel und denken android.support.design.widget.NavigationView app:headerLayout="@layout/nav_header_main"Sie daran, die Zeile zu entfernen, da Sie bereits programmgesteuert aufgeblasen haben
MilapTank
@ milapTank Kommentar half, da die Header-Ansicht zweimal aufgeblasen wurde, bis ich die von ihm vorgeschlagene Zeile aus meinem XML entfernte.
Taimur Khan
25

Fügen Sie keine Header in XML hinzu. Fügen Sie sie mit Code hinzu, indem Sie das Layout aufblasen

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
quelle
Ja, das ist leicht das Ergebnis, danke bhai.
Sajid Khan
7

In 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
quelle
6

Zuerst müssen Sie wie folgt auf die Navigationsleiste in Ihrer MainActivity (oder der aufrufenden Aktivität) zugreifen:

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

Dann müssen Sie das Header-Layout aus der Datei activity_main.xml entfernen, da das Layout in der MainActivity programmgesteuert aufgeblasen wird. Ihre activity_main.xml sollte folgendermaßen aussehen:

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

In Ihrer MainActivity füllen wir dann das nav_header_main-Layout auf und erhalten Zugriff auf seine Ansichten, in diesem Fall ImageView und 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);

Sie können mehr lesen hier

Ikhiloya Imokhai
quelle
4

Hier ist mein Code unten, der perfekt funktioniert. Fügen Sie den Header nicht im NavigationView-Tag in activity_main.xml hinzu

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

Fügen Sie den Header programmgesteuert mit dem folgenden Code hinzu

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.
quelle
hat bei mir nicht funktioniert, es zeigt leeren nav_header. (ohne Text und Bild)
Maximus
@maximus Ich werde den Code auf GitHub hochladen und du kannst nach dem Fehler suchen, den du gemacht hast.
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);

            }

        }
    }

Hoffe das hilft.

Saurabh Singh
quelle
2

Ich weiß, dass dies ein alter Beitrag ist, aber ich bin mir sicher, dass dies jemandem auf der Straße helfen könnte.

Sie können einfach das headerView-Element der Navigationsansicht abrufen, indem Sie Folgendes tun:

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

Ich hoffe, dass dies jemandem hilft.

Ronnie
quelle
Wie bekomme ich die Textansicht? wäre es mParent.findViewById()oder nur findViewById()?
Si8
kann mView.findViewById (R.id.text_view) verwenden;
Ronnie
2

Sie können auch Kotlinx-Funktionen verwenden

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

Ich habe diesen Code selbst mit einer gewissen Logik erstellt ... Es funktioniert zu 100% ..... Bitte stimmen Sie meinen Ans zu.

Die Text- und Bildansicht stammen aus @ layout / nav_header_main.xml

Prajwal Waingankar
quelle
2
val navigationView: NavigationView =  findViewById(R.id.nv)
val header: View = navigationView.getHeaderView(0)
val teext: TextView = header.findViewById(R.id.profilename)
teext.text = "eejfgjt"

Dies wird Ihr Problem <3 beheben

Mohammad Khair PK
quelle
1

BEARBEITEN: Funktioniert mit der Designbibliothek bis 23.0.1, funktioniert jedoch nicht mit 23.1.0

In der Hauptlayout-XML haben Sie NavigationViewdefiniert, in welcher Verwendung Sie app:headerLayoutdie Header-Ansicht festlegen.

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

Und das @layout/nav_drawer_headerwird der Platzhalter des Bildes und der Texte sein.

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>

Und in der Hauptklasse, können Sie nehmen Griff Imageviewund TextViewso wie normale andere Ansichten.

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

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

Hoffe das hilft.

Kavin Prabhu
quelle
Ich habe es implementiert und es funktioniert ohne Probleme. Ich benutze diesen Weg schon ziemlich lange.
Kavin Prabhu
Ich benutze dies in der Designbibliothek 22.2.1 und es funktioniert gut. Nie versucht am 23.1.0
Kavin Prabhu
Ich habe es versucht, aber die Anwendung stürzt ab. Log Cat Fehler zeigt in der Nähe von navHeaderTitle.setText ("Anwendungsname")
Kalai
Sie verwenden die Support-Bibliothek 23.1.0? Wenn ja, schauen Sie bitte in den Link von @PareshMayani im obigen Kommentar.
Kavin Prabhu
1

Es ist ein alter Beitrag, aber er ist neu für mich. So ist es einfach! In diesem Teil des Codes:

 public boolean onNavigationItemSelected(MenuItem item) {

} Habe ich eine ImageView an das LinearLayout gebunden, das die ImageView aus dem unten aufgeführten Beispiel enthält. Beachten Sie: Es ist derselbe Code, den Sie erhalten, wenn Sie ein neues Projekt starten und die Vorlage "Navigation Drawer Activity" auswählen:

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

Ich habe das LinearLayout und die ID in nav_header_main.xml angegeben (in meinem Fall habe ich 'navigation_header_container' ausgewählt, also ging es so:

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

Hinweis: Ich habe oben vor onCreate (MainActivity) einen privaten ImageView ivCloseDrawer deklariert.

Es hat gut funktioniert! Hoffe es hilft, Mit freundlichen Grüßen.

Heitor
quelle
0

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

Роман Бяков
quelle
1
Hallo @ Роман Бяков, willkommen bei Stack Overflow. Vielen Dank für Ihren Beitrag. Ist dir bewusst, dass die Frage älter als 4 Monate ist :-)? Ich bin mir nicht sicher, ob die Antwort noch benötigt wird. Versuchen Sie jedoch bei anderen Antworten, ein wenig mehr zu erklären. Was ist yourviewin Ihrem Vorschlag und wo sollte das OP Ihren Code ablegen? Sollte sie / er die Zeilen hinzufügen oder dieselben Zeilen durch Ihre ersetzen ? Erklärungen wie diese helfen Ihnen, Ihre Antwort zu versuchen und den Wert Ihres Beitrags zu erkennen. Viel Glück.
Peter_the_oak
Für das, was es wert ist, gibt es keine endgültige Antwort auf dieses Problem und es ist immer noch aktiv: Ist Ihnen bewusst, dass es seit Ablauf dieser willkürlichen Frist von 4 Monaten 3 neue Beiträge gab :-)? Sie sind sich nicht sicher, ob Ihr Kommentar benötigt wird. Achten Sie jedoch bei zukünftigen Kommentaren darauf, die Beiträge zu verbessern, anstatt sie insgesamt zu entmutigen.
SQLiteNoob
Viele Fragen, die älter als 4 Monate sind, werden noch beantwortet. In der Tat erhalten einige Fragen, die viel älter sind (einige Jahre alt), immer noch Antworten! Und das ist gut so. Obwohl das OP möglicherweise seine Antwort erhalten hat, gibt es Personen, die dieselbe Frage haben und für die die Frage mit dem vorhandenen Antwortpool unbeantwortet bleibt. Da StackOverflow das erneute Posten derselben Frage verhindert, helfen neue Antworten anderen Personen mit derselben Frage. Darüber hinaus ändern sich APIs im Laufe der Zeit und alte Antworten enthalten manchmal Code, der möglicherweise veraltet ist.
EIN
0

Hier ist die Methode, mit der Sie die Header-Ansicht abrufen und Daten genau festlegen können

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
quelle
0

Wenn Sie Bindungen verwenden, können Sie dies tun

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