【问题标题】:How to get view from drawer header layout with binding in activity?如何通过活动绑定从抽屉标题布局中获取视图?
【发布时间】:2015-11-21 15:47:24
【问题描述】:

这是我的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;**

【问题讨论】:

    标签: android android-activity view binding drawer


    【解决方案1】:

    如果您设置了app:headerLayout="@layout/drawer_header,那么您就不必再次膨胀视图。您可以只使用.bind 而不是.inflate

    你可以得到已经膨胀的标题视图并像这样绑定它:

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

    【讨论】:

    • 这可能是最简单的解决方案了。
    • 迄今为止最好的解决方案
    • 我发现它非常有用。像魅力一样工作。
    【解决方案2】:

    更新的解决方案(2015 年 11 月 13 日)

    解决方案:将您的设计支持库更新为 23.1.1

    设计支持库23.1.1的更改:

    • getHeaderView 方法添加到NavigationView 类。
    • 修复了运行 Android 4.0(API 级别 15)及更低版本的设备上 FloatingActionButton 对象的透明背景问题。 (问题 183315)

    更多信息请见https://developer.android.com/tools/support-library/index.html


    原解决方案

    我不知道为什么没有提供标题视图的方法 以编程方式附加。

    相反,这里有两个解决方案:

    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 文件以获取 23.1.1,getHeaderView(int index) 方法就会在那里。
    • 救命稻草!! +1 .. 但是你必须从 xml 中删除 app:headerLayout="@layout/header_left" 否则它会膨胀两个标题......
    【解决方案3】:

    我有一个稍微干净的解决方案,我不必使用负责向 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>
    

    如您所见,NavigationView 中没有 app:headerLayout,但我添加了我的自定义 app:model,以及我想要传递给标题布局的数据。 我是如何定义这个自定义参数的?按扩展类:

    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>
    

    【讨论】:

    • 这个回复应该是被接受的答案。很棒的帖子。
    • 这很混乱,你能展示一下 ScoreViewModel 类吗?
    【解决方案4】:

    我有/遇到过同样的问题。

    一种解决方法是扩展标题视图并以编程方式添加它。

    像这样:

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

    所以删除 app:headerLayout 并以编程方式进行。我确实认为谷歌应该在这里解决核心问题,无论是在设计库中还是在数据绑定库中。

    【讨论】:

    • 要保持 layout_height 中指定的 RelativeLayout 的高度,请将 RelativeLayout 放入框架布局中:&lt;FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" &gt;
    • 您是否注意到 design-23.1.0 的变化?我的代码现在不能工作了。
    【解决方案5】:

    这里有一个非常简单的解决方案。假设您将 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 中 ID 为 textView2 的 TextView。因此,您只需在活动中使用此代码:

    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!");
    

    无需夸大或干扰您现有的代码等。

    【讨论】:

      【解决方案6】:
      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;
              }
          }
      });
      

      【讨论】:

        【解决方案7】:

        试试这个对我有用的 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>
        

        在你的活动中:

        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

        【讨论】:

          【解决方案8】:
          • 编辑您的 gradle 文件以将 com.android.support 库更新到版本 23.1.1 或更高版本。

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

          【讨论】:

            【解决方案9】:

            我已经从 Android sdk 管理器更新了构建工具,然后23.1.0 对我来说也可以正常工作。

            我使用的是buildToolsVersion "23.0.2",之前是23.0.1

            并且没有必要使用:

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

            在你的activity中你可以直接使用:

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

            【讨论】:

              【解决方案10】:

              只需放置 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);
              

              【讨论】:

                【解决方案11】:

                它对我有用。

                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>
                

                【讨论】:

                • 您需要描述您所做的事情,而不仅仅是发布代码......努力为他人带来最大的利益
                【解决方案12】:

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

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

                【讨论】:

                • 这不是使用绑定。我知道该怎么做。不过谢谢。
                猜你喜欢
                • 2023-03-14
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-08-22
                • 2021-11-15
                • 1970-01-01
                相关资源
                最近更新 更多