如何从活动中绑定抽屉页眉布局来获取视图?

问题描述:

所以这是我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> 

,我使用的活动绑定,所以我没有使用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布局中获取视图,但是当我试图获取的视图不存在时,我无法在绑定对象中看到该变量。

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;** 

13/11/2015

http://developer.android.com/tools/support-library/index.html

更新设计支持库23.1.0至23.1.1

Changes for Design Support library: 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)

==== ===============

我不知道为什么没有方法,该方法提供由编程

1.solution

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

2.解决方案

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

ImageView iv = (ImageView) headerView.findViewById(...) 
+5

只需更新您的gradle文件即可获得23.1.1,并且getHeaderView(int index)方法将会在那里。 – Renascienza

+4

拯救生命! +1 ..但是你必须从xml中删除应用程序:headerLayout =“@ layout/header_left”,否则会膨胀两个标头... –

+4

此解决方案未使用数据绑定... – Mussa

我有/有同样的问题。

解决方法是膨胀标题视图并以编程方式添加它。

像这样:

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

所以删除应用:headerLayout并做到这一点编程。我认为谷歌应该在这里解决核心问题,无论是在设计库还是在数据绑定库中。

+0

为了保持layout_height指定的RelativeLayout的高度,把RelativeLayout的成框架布局:' android:layout_width =“match_parent” android:layout_height =“wrap_content” > ' – geekyvad

+1

你有没有注意到design-23.1.0的变化?我的代码现在无法工作。 – RogerParis

你可以这样做。首先初始化导航视图。

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); 
+2

这不是使用绑定。我知道该怎么做。但是,谢谢。 – RogerParis

  • 编辑您的gradle这个连接头视图 文件更新com.android。支持库到版本23.1.1或更高版本。

  • 使用navigationView.getHeaderView(i),其中iheaderview的索引。如果您只是在布局上定义此视图,则为0

我已经更新了Android SDK管理器的构建工具,然后23.1.0也适用于我。

我正在使用buildToolsVersion "23.0.2"在此之前它是23.0.1

而且也没有必要使用:

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

在你的活动,你可以直接使用:

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

+3

您需要描述您所做的不只是邮政编码...努力最大限度地为他人带来收益 –

+0

这也对我有帮助 – Herry

我有一个稍微更干净的解决方案,我不必“污染”片段/活动代码负责膨胀和添加标题视图到NavigationView。我实现了NavigationView的扩展类。我这样做,是这样的:我的活动

布局:

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

正如你所看到的,没有应用:headerLayout在NavigationView,但我已经加入我的自定义应用程序:模型,我想传递给标题布局的数据。 我是如何定义这个自定义参数的?通过扩展类:

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

只需将该类放置在项目的任何位置即可。而我的头的布局:

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

+0

这个答复应该被接受回答。优秀的职位。 – Mussa

如果设置app:headerLayout="@layout/drawer_header那么你就不必再膨胀的观点。您可以使用.bind而不是.inflate

你可以得到已膨胀头视图,并将其绑定这样的:

View headerView = binding.navigationView.getHeaderView(0); 
DrawerHeaderBinding headerBinding = DrawerHeaderBinding.bind(headerView); 
+1

这可能是最简单的解决方案。 –

与数据绑定库工作对我来说试试这个。

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> 

和您的活动中:

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

,并确保您的活动器具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/nav_drawer_header" 
    app:menu="@menu/menu_nav_drawer"/> 

而且要在nav_drawer_header.xml拥有的textView2的ID来访问一个TextView。所以你只需使用此代码在您的活动:

View headerContainer = navigationView.getHeaderView(0); // This returns the container layout in nav_drawer_header.xml (e.g., your RelativeLayout or LinearLayout) 
TextView textView2 = (TextView)headerContainer.findViewById(R.id.textView2); 
textView2.setText("Sorted!"); 

无需充气或与您现有的代码干扰等