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;**
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 classeNavigationView
.- 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.
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)
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>
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.
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);
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;
}
}
});
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.
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
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
.
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);
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);