web-dev-qa-db-fra.com

Comment obtenir une vue de la disposition des en-têtes de tiroir avec une liaison active?

Voici donc mon activité_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout 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"
        tools:context="MainActivity"
    >
    <!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->
    <Android.support.v4.widget.DrawerLayout
        Android:id="@+id/drawer_layout"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        >

        <!-- As the main content view, the view below consumes the entire
             space available using match_parent in both dimensions. -->

        <RelativeLayout
            Android:layout_width="match_parent"
            Android:layout_height="match_parent">

            <LinearLayout
                Android:id="@+id/ll_container"
                Android:layout_width="match_parent"
                Android:layout_height="match_parent"
                Android:orientation="vertical">

                <Android.support.v7.widget.Toolbar
                    Android:id="@+id/my_awesome_toolbar"
                    Android:layout_width="match_parent"
                    Android:layout_height="wrap_content"
                    Android:background="@Android:color/black"
                    Android:fitsSystemWindows="true"
                    >

                    <TextView
                        Android:id="@+id/toolbar_title"
                        Android:layout_width="wrap_content"
                        Android:layout_height="wrap_content"
                        Android:layout_marginLeft="10dp"
                        Android:layout_marginStart="10dp"
                        Android:textColor="@Android:color/white"
                        Android:textSize="@dimen/abc_text_size_title_material_toolbar"
                        tools:text="@string/default_toolbar_title"/>

                </Android.support.v7.widget.Toolbar>


                <FrameLayout
                    Android:id="@+id/container"
                    Android:layout_width="match_parent"
                    Android:layout_height="match_parent">

                </FrameLayout>
            </LinearLayout>

            <Android.support.design.widget.FloatingActionButton
                Android:id="@+id/fab_fuf"
                Android:layout_width="wrap_content"
                Android:layout_height="wrap_content"
                Android:layout_alignParentBottom="true"
                Android:layout_alignParentEnd="true"
                Android:layout_alignParentRight="true"
                Android:layout_marginBottom="20dp"
                Android:layout_marginEnd="20dp"
                Android:layout_marginRight="20dp"
                Android:src="@drawable/flamme"
                app:fabSize="normal"
                />
        </RelativeLayout>

        <Android.support.design.widget.NavigationView
            Android:id="@+id/navigation_view"
            Android:layout_width="wrap_content"
            Android:layout_height="match_parent"
            Android:layout_gravity="start"
            Android:background="@Android:color/black"
            **app:headerLayout="@layout/drawer_header"**
            app:itemTextColor="@color/drawer_item_color_selector"
            app:menu="@menu/menu_drawer"/>

    </Android.support.v4.widget.DrawerLayout>
</layout>

et j'utilise la liaison pour l'activité, je n'ai donc pas à utiliser findViewById et à la lancer, etc., comme ceci: 

ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        Toolbar toolbar = binding.myAwesomeToolbar;
        toolbarTitle = binding.toolbarTitle;
        BalrogFontsHelper.SetKhandBoldToView(toolbarTitle);
        setSupportActionBar(toolbar);
        final ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setHomeAsUpIndicator(R.drawable.ic_dehaze_white_24);
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
            actionBar.setDisplayShowTitleEnabled(false);
        }


        drawerLayout = binding.drawerLayout;
        **tvLoggedUserEmail = (TextView) findViewById(R.id.tv_logged_user_email);**
        BalrogFontsHelper.SetKhandBoldToView(tvLoggedUserEmail);

Comme vous pouvez le constater, je peux obtenir les vues qui se trouvent directement dans la présentation activity_main.xml en les liant, mais lorsque la vue que j'essaie d'obtenir n'est pas là, je ne peux pas voir la variable dans l'objet de liaison.

tiroir_header.xml:

    <?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
                Android:layout_width="match_parent"
                Android:layout_height="96dp"
                xmlns:tools="http://schemas.Android.com/tools"
                Android:background="@Android:color/black"
                Android:theme="@style/ThemeOverlay.AppCompat.Dark">


    <TextView
        Android:id="@+id/tv_logged_user_email"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_centerVertical="true"
        Android:layout_marginLeft="16dp"
        tools:text="@string/login_placeholder_email"
        Android:textAllCaps="true"
        Android:textAppearance="@style/TextAppearance.AppCompat.Body2"
        Android:textSize="20sp"/>


</RelativeLayout>

Comment pourrais-je obtenir ce textView tv_logged_user_email de manière contraignante, donc j'ai:

**tvLoggedUserEmail = binding.tvLoggedUserEmail;**
27
RogerParis

Solution mise à jour (13/11/2015)

Solution: mettez à jour votre bibliothèque de support de conception avec 23.1.1:

Modifications pour la bibliothèque de support à la conception 23.1.1:

  • Ajout de la méthode getHeaderView à la classe NavigationView.
  • Correction d'un problème d'arrière-plan transparent pour un objet FloatingActionButton sur des appareils fonctionnant sous Android 4.0 (niveau d'API 15) et inférieur. (Numéro 183315)

Voir https://developer.Android.com/tools/support-library/index.html pour plus d'informations.


Solution originale

Je ne sais pas pourquoi il n'y a pas de méthode fournissant une vue d'en-tête Attachée par programme.

Au lieu de cela, voici deux solutions:

NavigationView navigationView = (NavigationView) findViewById(R.id.navigation);
View headerView = navigationView.inflateHeaderView(R.layout.header_layout)
ImageView iv = (ImageView)headerview.findViewById(R.id.your_image_view)

Ou:

NavigationView navigationView = (NavigationView) findViewById(R.id.navigation);
View headerView = LayoutInflater.from(this).inflate(R.layout.header_layout, navigationView, false);
navigationView.addHeaderView(headerView);

ImageView iv = (ImageView) headerView.findViewById(R.id.yourImageView)
32
leejaycoke

J'ai une solution légèrement plus propre, dans laquelle je n'ai pas à polluer un fragment/activité avec un code chargé de gonfler et d'ajouter une vue d'en-tête à NavigationView. J'ai implémenté la classe d'extension pour NavigationView. J'ai fait ça comme ça:

Mise en page de mon activité:

<data>
    <variable
        name="dashboard"
        type="ramps.view.model.DashboardScreenViewModel"/>
</data>

<Android.support.v4.widget.DrawerLayout
    Android:id="@+id/drawer_layout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/activity_dashboard"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        bind:dashboard="@{dashboard}"
        />

    <Android.support.design.widget.NavigationView
        Android:id="@+id/nav_view"
        Android:background="@color/white"
        Android:layout_width="wrap_content"
        Android:layout_height="match_parent"
        Android:layout_gravity="start"
        Android:fitsSystemWindows="true"
        app:navigationItemSelectedListener="@{dashboard.onMenuItemSelected}"
        app:model="@{dashboard.score}"
        app:menu="@menu/activity_main_drawer"/>

</Android.support.v4.widget.DrawerLayout>

Comme vous pouvez le constater, il n'y a pas d'application: headerLayout dans NavigationView, mais j'ai ajouté mon application personnalisée: model, avec les données que je souhaite transmettre à la présentation d'en-tête . Comment ai-je défini ce paramètre personnalisé? Par classe d'extension:

public class NavigationViewExtensions {

@BindingAdapter({"bind:model"})
public static void loadHeader(NavigationView view, ScoreViewModel model) {
    ViewNavigationHeaderBinding binding = ViewNavigationHeaderBinding.inflate(LayoutInflater.from(view.getContext()));
    binding.setScore(model);
    binding.executePendingBindings();
    view.addHeaderView(binding.getRoot());
  }
}

Placez simplement cette classe n'importe où dans votre projet. Et la mise en page de mon en-tête:

<layout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:bind="http://schemas.Android.com/apk/res-auto"
>

<data>

    <import type="Android.view.View"/>

    <variable
        name="score"
        type="ramps.view.model.ScoreViewModel"/>
</data>

<LinearLayout
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:background="@color/graphite"
    Android:gravity="bottom"
    Android:orientation="vertical"
    Android:paddingBottom="@dimen/activity_vertical_margin_large"
    Android:paddingLeft="@dimen/activity_horizontal_margin"
    Android:paddingRight="@dimen/activity_horizontal_margin"
    Android:paddingTop="@dimen/activity_vertical_margin_large"
    Android:theme="@style/ThemeOverlay.AppCompat.Dark">

    <include
        Android:id="@+id/player_details_header_score"
        layout="@layout/view_avatar_score_header"
        bind:score="@{score}"/>

</LinearLayout>

14
Ramps

J'ai eu le même problème.

Une solution de contournement consiste à gonfler la vue en-tête et à l'ajouter par programme.

Comme ça:

DrawerHeaderBinding drawerHeaderBinding = DrawerHeaderBinding.inflate(LayoutInflater.from(navigationView.getContext()));
navigationView.addHeaderView(drawerHeaderBinding.getRoot());
drawerHeaderBinding.tvLoggedUserEmail = "email";
drawerHeaderBinding.executePendingBindings();

Supprimez donc l’application: headerLayout et programmez-la. Je pense néanmoins que Google devrait résoudre le problème principal, que ce soit dans la bibliothèque de conception ou dans la bibliothèque de liaisons de données.

10
Tosa

Si vous définissez app:headerLayout="@layout/drawer_header, vous n'avez pas à gonfler à nouveau la vue. Vous pouvez simplement utiliser .bind au lieu de .inflate

Vous pouvez obtenir la vue d'en-tête déjà gonflée et la lier comme ceci:

View headerView = binding.navigationView.getHeaderView(0);
DrawerHeaderBinding headerBinding = DrawerHeaderBinding.bind(headerView);
8
stefana
ImageView imageView = (ImageView) navigationView.getHeaderView(0).findViewById(R.id.imageButton);

imageView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

        if (flag) {
            navigationView.getMenu().clear(); //clear old inflated items.
            navigationView.inflateMenu(R.menu.drawer_view1);
            flag = false;
        } else {
            navigationView.getMenu().clear(); //clear old inflated items.
            navigationView.inflateMenu(R.menu.drawer_view);
            flag = true;
        }
    }
});
8
user5783673

Une solution assez simple ici. Supposons que vous ayez ajouté votre NavigationView en tant que

<Android.support.design.widget.NavigationView
    Android:id="@+id/navigationView"
    Android:layout_width="wrap_content"
    Android:layout_height="match_parent"
    Android:layout_gravity="start"
    Android:fitsSystemWindows="true"
    app:headerLayout="@layout/my_nav_drawer_header"
    app:menu="@menu/menu_nav_drawer"/>

Et que vous souhaitiez accéder à un TextView dans my_nav_drawer_header.xml dont l'identifiant est textView2. Donc, vous utiliseriez simplement ce code dans votre activité:

View headerContainer = navigationView.getHeaderView(0); // This returns the container layout from your navigation drawer header layout file (e.g., the parent RelativeLayout/LinearLayout in your my_nav_drawer_header.xml file)
TextView textView2 = (TextView)headerContainer.findViewById(R.id.textView2);
textView2.setText("Sorted!");

Pas besoin de gonfler ou d'interférer avec votre code existant, etc.

4

Essayez ceci avec la bibliothèque DataBinding, cela fonctionne pour moi.

navigation_view_header.xml:

<layout xmlns:Android="http://schemas.Android.com/apk/res/Android">
<RelativeLayout
    Android:layout_width="match_parent"
    Android:layout_height="@dimen/navigation_view_header_height"
    Android:paddingLeft="@dimen/navigation_view_padding"
    Android:paddingTop="@dimen/navigation_view_top_padding"
    Android:background="@color/colorPrimary">


    <ImageView
        Android:id="@+id/avatar"
        Android:layout_width="@dimen/avatar_dimen"
        Android:layout_height="@dimen/avatar_dimen"
        Android:contentDescription="@null"
        Android:src="@drawable/default_avatar" />

    <TextView
        Android:id="@+id/profile_email"
        Android:layout_width="match_parent"
        Android:layout_height="48dp"
        Android:layout_below="@+id/avatar"
        Android:text="email"
        Android:textColor="@color/white"
        Android:layout_alignParentBottom="true"
        Android:gravity="center_vertical" />

</RelativeLayout>
</layout>

activity_main.xml:

<layout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto">
    <data>
        <variable
            name="navigationItemSelectedListener"
            type="com.example.MainActivity"/>
    </data>
<Android.support.v4.widget.DrawerLayout
    Android:id="@+id/drawer_layout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:fitsSystemWindows="true"
    Android:tag="layout">

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:orientation="vertical">

        <Android.support.v7.widget.Toolbar
            Android:id="@+id/my_toolbar"
            Android:layout_width="match_parent"
            Android:layout_height="?attr/actionBarSize"
            app:titleTextColor="@color/white"
            Android:background="@color/colorPrimary"
            app:theme="@style/Toolbar.Theme"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

        <FrameLayout
            Android:id="@+id/fragment_container"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent" />
    </LinearLayout>

    <Android.support.design.widget.NavigationView
        Android:id="@+id/navigation_view"
        Android:layout_width="@dimen/navigation_view_width"
        Android:layout_height="match_parent"
        Android:layout_gravity="start"
        Android:fitsSystemWindows="true"
        app:theme="@style/Theme.AppCompat.Light"
        app:menu="@menu/drawer_menu"
        app:navigationItemSelectedListener="@{navigationItemSelectedListener::onNavigationItemSelected}"/>

</Android.support.v4.widget.DrawerLayout>
</layout>

et au sein de votre activité:

ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this,
                R.layout.activity_main);
activityMainBinding.setNavigationItemSelectedListener(this);/* with this line navigation menu item selection events are handled in onNavigationItemSelected() specified in navigation_view_header.xml*/

NavigationViewHeaderBinding navigationViewHeaderBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.navigation_view_header,activityMainBinding.navigationView,false);
        activityMainBinding.navigationView.addHeaderView(navigationViewHeaderBinding.getRoot());

et assurez-vous que votre activité implémente NavigationView.OnNavigationItemSelectedListener

1
Yasser Khayyal
  • Editez votre fichier Gradle pour mettre à jour com.Android.support libraries en version 23.1.1 ou version ultérieure.

  • Utilisez navigationView.getHeaderView(i), où i est l'index de headerview. Si vous venez de définir cette vue sur la mise en page, est 0

0
Renascienza

Il suffit de mettre navigationView.getHeaderView (0) puis d'utiliser n'importe quelle vue

        TextView profile,info;
        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        profile = navigationView.getHeaderView(0).findViewById(R.id.profile);
        info = navigationView.getHeaderView(0).findViewById(R.id.info);
        profile.setOnClickListener(this);
        info.setOnClickListener(this);
0
milan pithadia

J'ai mis à jour les outils de compilation à partir d'Android sdk manager, alors 23.1.0 fonctionne également très bien pour moi.

J'utilise buildToolsVersion "23.0.2" Avant cela, c'était 23.0.1.

et il n'y a pas besoin d'utiliser:

(View) navigationView.findViewById(R.id.idOfViewFromHeaderView);

Dans votre activité, vous pouvez directement utiliser:

(View) findViewById(R.id.idOfViewFromHeaderView);
0
Muhammad Adil