如何通过 activity 中的绑定从抽屉 header 布局获取视图?
How to get view from drawer header layout with binding in activity?
所以这是我的 activity_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>
我正在为 activity 使用绑定,所以我不必使用 findViewById 并强制转换它等等。像这样:
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);
如您所见,我可以通过绑定获取直接位于 activity_main.xml 布局中的视图,但是当我尝试获取的视图不存在时,我看不到绑定中的变量object.
drawer_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>
我怎样才能以绑定方式获得这个 tv_logged_user_email TextView,所以我有:
**tvLoggedUserEmail = binding.tvLoggedUserEmail;**
我have/had同样的问题
解决方法是膨胀 header 视图并以编程方式添加它。
像这样:
DrawerHeaderBinding drawerHeaderBinding = DrawerHeaderBinding.inflate(LayoutInflater.from(navigationView.getContext()));
navigationView.addHeaderView(drawerHeaderBinding.getRoot());
drawerHeaderBinding.tvLoggedUserEmail = "email";
drawerHeaderBinding.executePendingBindings();
所以删除 app:headerLayout 并以编程方式执行。我确实认为 google 应该在设计库或数据绑定库中解决这里的核心问题。
你可以做到这一点。首先初始化导航视图。
NavigationView navigationView = (NavigationView) findViewById(R.id.navigation_view);
然后初始化 navigationView 中的所有视图。
CircleImageView circleView = (CircleImageView) navigationView.findViewById(R.id.circleView);
TextView name = (TextView) navigationView.findViewById(R.id.name);
TextView email = (TextView) navigationView.findViewById(R.id.email);
LinearLayout header = (LinearLayout) navigationView.findViewById(R.id.header);
然后您可以根据需要使用这些视图。
例如:
name.setText(NAME);
email.setText(EMAIL);
更新解决方案 (13/11/2015)
解决方案:将您的设计支持库更新为 23.1.1
:
Changes for Design Support library 23.1.1
:
- Added the
getHeaderView
method to the NavigationView
class.
- Fixed a transparent background issue for a
FloatingActionButton
object on devices running Android 4.0 (API level 15) and lower. (Issue 183315)
有关详细信息,请参阅 https://developer.android.com/tools/support-library/index.html
原解
不知道为什么没有提供header视图的方法
以编程方式附加。
相反,这里有两个解决方案:
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)
或:
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)
编辑您的 gradle 文件以将 com.android.support 库更新到版本 23.1.1 或以后。
使用navigationView.getHeaderView(i)
,其中i
是headerview
的索引。如果您刚刚在布局上定义此视图,则为 0
。
我已经从 Android sdk 管理器更新了构建工具,然后 23.1.0
对我来说也工作正常。
我正在使用 buildToolsVersion "23.0.2"
在此之前它是 23.0.1
。
并且不需要使用:
(View) navigationView.findViewById(R.id.idOfViewFromHeaderView);
在你的activity中你可以直接使用:
(View) findViewById(R.id.idOfViewFromHeaderView);
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;
}
}
});
对我有用。
MainActivity.java:
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
NavHeaderMainBinding binding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.nav_header_main, navigationView, false);
navigationView.addHeaderView(binding.getRoot());
activity_main.xml:
<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">
<RelativeLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="@layout/toolbar" />
</android.support.design.widget.AppBarLayout>
</RelativeLayout>
<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>
nav_header.xml:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="account"
type="lonja.dreamteam.su.trainingdiary.view_model.AccountViewModel"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height"
android:background="@drawable/header_background"
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">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/imageView"
android:layout_width="72dp"
android:layout_height="72dp"
android:src="@{account.sex}"
app:civ_border_color="@color/colorAccent"
app:civ_border_width="0dp" />
<TextView
android:id="@+id/userName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:text="@{account.name}"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
</LinearLayout>
我有一个更简洁的解决方案,我不必 "pollute" fragment/activity 使用负责膨胀视图并将 header 视图添加到 NavigationView 的代码。我为 NavigationView 实现了扩展 class。我是这样做的:
我的布局activity:
<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>
如您所见,NavigationView 中没有 app:headerLayout,但我添加了我的自定义 app:model,其中包含我要传递给 header 布局的数据。
我是如何定义这个自定义参数的?通过扩展 class:
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());
}
}
只需将此 class 放在您项目中的任何位置。以及我的布局 header:
<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>
如果您设置 app:headerLayout="@layout/drawer_header
则您不必再次膨胀视图。您可以只使用 .bind
而不是 .inflate
。
您可以获得已经膨胀的 header 视图并像这样绑定它:
View headerView = binding.navigationView.getHeaderView(0);
DrawerHeaderBinding headerBinding = DrawerHeaderBinding.bind(headerView);
尝试使用适合我的 DataBinding 库。
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>
并在您的 activity 内:
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());
并确保您的 activity 实施 NavigationView.OnNavigationItemSelectedListener
这是一个非常简单的解决方案。假设您将 NavigationView 添加为
<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"/>
并且您想访问 my_nav_drawer_header.xml
中的 TextView,其 ID 为 textView2
。因此,您只需在 activity:
中使用此代码
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!");
无需膨胀或干扰您现有的代码等
只需输入 navigationView.getHeaderView(0) 然后使用任何视图
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);
所以这是我的 activity_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>
我正在为 activity 使用绑定,所以我不必使用 findViewById 并强制转换它等等。像这样:
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);
如您所见,我可以通过绑定获取直接位于 activity_main.xml 布局中的视图,但是当我尝试获取的视图不存在时,我看不到绑定中的变量object.
drawer_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>
我怎样才能以绑定方式获得这个 tv_logged_user_email TextView,所以我有:
**tvLoggedUserEmail = binding.tvLoggedUserEmail;**
我have/had同样的问题
解决方法是膨胀 header 视图并以编程方式添加它。
像这样:
DrawerHeaderBinding drawerHeaderBinding = DrawerHeaderBinding.inflate(LayoutInflater.from(navigationView.getContext()));
navigationView.addHeaderView(drawerHeaderBinding.getRoot());
drawerHeaderBinding.tvLoggedUserEmail = "email";
drawerHeaderBinding.executePendingBindings();
所以删除 app:headerLayout 并以编程方式执行。我确实认为 google 应该在设计库或数据绑定库中解决这里的核心问题。
你可以做到这一点。首先初始化导航视图。
NavigationView navigationView = (NavigationView) findViewById(R.id.navigation_view);
然后初始化 navigationView 中的所有视图。
CircleImageView circleView = (CircleImageView) navigationView.findViewById(R.id.circleView);
TextView name = (TextView) navigationView.findViewById(R.id.name);
TextView email = (TextView) navigationView.findViewById(R.id.email);
LinearLayout header = (LinearLayout) navigationView.findViewById(R.id.header);
然后您可以根据需要使用这些视图。 例如:
name.setText(NAME);
email.setText(EMAIL);
更新解决方案 (13/11/2015)
解决方案:将您的设计支持库更新为 23.1.1
:
Changes for Design Support library
23.1.1
:
- Added the
getHeaderView
method to theNavigationView
class.- Fixed a transparent background issue for a
FloatingActionButton
object on devices running Android 4.0 (API level 15) and lower. (Issue 183315)
有关详细信息,请参阅 https://developer.android.com/tools/support-library/index.html
原解
不知道为什么没有提供header视图的方法 以编程方式附加。
相反,这里有两个解决方案:
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)
或:
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)
编辑您的 gradle 文件以将 com.android.support 库更新到版本 23.1.1 或以后。
使用
navigationView.getHeaderView(i)
,其中i
是headerview
的索引。如果您刚刚在布局上定义此视图,则为0
。
我已经从 Android sdk 管理器更新了构建工具,然后 23.1.0
对我来说也工作正常。
我正在使用 buildToolsVersion "23.0.2"
在此之前它是 23.0.1
。
并且不需要使用:
(View) navigationView.findViewById(R.id.idOfViewFromHeaderView);
在你的activity中你可以直接使用:
(View) findViewById(R.id.idOfViewFromHeaderView);
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;
}
}
});
对我有用。
MainActivity.java:
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
NavHeaderMainBinding binding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.nav_header_main, navigationView, false);
navigationView.addHeaderView(binding.getRoot());
activity_main.xml:
<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">
<RelativeLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="@layout/toolbar" />
</android.support.design.widget.AppBarLayout>
</RelativeLayout>
<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>
nav_header.xml:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="account"
type="lonja.dreamteam.su.trainingdiary.view_model.AccountViewModel"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height"
android:background="@drawable/header_background"
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">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/imageView"
android:layout_width="72dp"
android:layout_height="72dp"
android:src="@{account.sex}"
app:civ_border_color="@color/colorAccent"
app:civ_border_width="0dp" />
<TextView
android:id="@+id/userName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:text="@{account.name}"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
</LinearLayout>
我有一个更简洁的解决方案,我不必 "pollute" fragment/activity 使用负责膨胀视图并将 header 视图添加到 NavigationView 的代码。我为 NavigationView 实现了扩展 class。我是这样做的:
我的布局activity:
<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>
如您所见,NavigationView 中没有 app:headerLayout,但我添加了我的自定义 app:model,其中包含我要传递给 header 布局的数据。 我是如何定义这个自定义参数的?通过扩展 class:
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());
}
}
只需将此 class 放在您项目中的任何位置。以及我的布局 header:
<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>
如果您设置 app:headerLayout="@layout/drawer_header
则您不必再次膨胀视图。您可以只使用 .bind
而不是 .inflate
。
您可以获得已经膨胀的 header 视图并像这样绑定它:
View headerView = binding.navigationView.getHeaderView(0);
DrawerHeaderBinding headerBinding = DrawerHeaderBinding.bind(headerView);
尝试使用适合我的 DataBinding 库。
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>
并在您的 activity 内:
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());
并确保您的 activity 实施 NavigationView.OnNavigationItemSelectedListener
这是一个非常简单的解决方案。假设您将 NavigationView 添加为
<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"/>
并且您想访问 my_nav_drawer_header.xml
中的 TextView,其 ID 为 textView2
。因此,您只需在 activity:
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!");
无需膨胀或干扰您现有的代码等
只需输入 navigationView.getHeaderView(0) 然后使用任何视图
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);