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

Rog*_*ris 30 binding android view drawer android-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>
Run Code Online (Sandbox Code Playgroud)

我正在使用绑定活动所以我不必使用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);
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我可以通过绑定直接获取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>
Run Code Online (Sandbox Code Playgroud)

我怎么能以绑定方式获取这个tv_logged_user_email TextView所以我有:

**tvLoggedUserEmail = binding.tvLoggedUserEmail;**
Run Code Online (Sandbox Code Playgroud)

小智 33

更新的解决方案(13/11/2015)

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

设计支持库的更改23.1.1:

  • getHeaderViewNavigationView课堂上添加了方法.
  • 修复了FloatingActionButton运行Android 4.0(API级别15)及更低版本的设备上的对象的透明背景问题.(问题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)
Run Code Online (Sandbox Code Playgroud)

要么:

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)
Run Code Online (Sandbox Code Playgroud)

  • 只需更新您的gradle文件即可获得23.1.1,并且getHeaderView(int index)方法将在那里. (7认同)
  • 生命保护!+1 ..但你必须从xml删除app:headerLayout ="@ layout/header_left",否则它会膨胀两个标题...... (4认同)

Ram*_*mps 19

我有一个稍微清洁的解决方案,我不需要使用负责膨胀和向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>
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,NavigationView中没有app:headerLayout,但我添加了我的自定义应用:模型,我想要传递给标题布局的数据.我是如何定义此自定义参数的?通过扩展类:

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());
  }
}
Run Code Online (Sandbox Code Playgroud)

只需将此类放在项目的任何位置即可.我的标题的布局:

<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>
Run Code Online (Sandbox Code Playgroud)

  • 这个回复应该被接受答案.优秀的帖子. (3认同)

ste*_*ana 13

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

您可以获取已经膨胀的标题视图并将其绑定为:

View headerView = binding.navigationView.getHeaderView(0);
DrawerHeaderBinding headerBinding = DrawerHeaderBinding.bind(headerView);
Run Code Online (Sandbox Code Playgroud)

  • 这可能是最简单的解决方案。 (2认同)

Tos*_*osa 11

我曾经有过同样的问题.

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

像这样:

DrawerHeaderBinding drawerHeaderBinding = DrawerHeaderBinding.inflate(LayoutInflater.from(navigationView.getContext()));
navigationView.addHeaderView(drawerHeaderBinding.getRoot());
drawerHeaderBinding.tvLoggedUserEmail = "email";
drawerHeaderBinding.executePendingBindings();
Run Code Online (Sandbox Code Playgroud)

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


小智 9

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;
        }
    }
});
Run Code Online (Sandbox Code Playgroud)


ban*_*ing 7

这里很简单的解决方案。假设您将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"/>
Run Code Online (Sandbox Code Playgroud)

并且您要访问my_nav_drawer_header.xmlID为的TextView textView2。因此,您只需在活动中使用以下代码:

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!");
Run Code Online (Sandbox Code Playgroud)

无需充实或干扰您现有的代码等。