【问题标题】:Custom layout with menu in NavigationView?NavigationView 中带有菜单的自定义布局?
【发布时间】:2017-06-24 00:17:48
【问题描述】:

我需要创建一个导航抽屉,这样,第一个菜单包含 5 个预定义项目(这些项目永远不会改变)。在第一个菜单下方,我想要第二个菜单,其中包含具有自定义布局的可变数量的项目。

用图片解释:

这是我现在的主要活动的样子:

<android.support.v4.widget.DrawerLayout
    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"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/main_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.design.widget.AppBarLayout
            android:id="@+id/appbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_scrollFlags="scroll|enterAlways"
                app:popupTheme="@style/AppTheme.PopupOverlay" />

            <android.support.design.widget.TabLayout
                android:id="@+id/tablayout"
                android:layout_width="match_parent"
                android:layout_height="48dp" />

        </android.support.design.widget.AppBarLayout>

        <android.support.v4.view.ViewPager
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    </android.support.design.widget.CoordinatorLayout>

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

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <include
                layout="@layout/nav_header_drawer" />

            <ListView
                android:id="@+id/drawer_listview"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="left"
                android:choiceMode="singleChoice" />

        </LinearLayout>

    </android.support.design.widget.NavigationView>

</android.support.v4.widget.DrawerLayout>

这可行,但现在我不能为NavigationView 使用app:menu="@menu/navigation_drawer_items" 属性,因为ListView 项与菜单项重叠。

这里是菜单 XML:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:title="Communicate">
        <menu>
            <item
                android:id="@+id/nav_share"
                android:icon="@drawable/ic_menu_share"
                android:title="Share" />
            <item
                android:id="@+id/nav_send"
                android:icon="@drawable/ic_menu_send"
                android:title="Send" />
        </menu>
    </item>
</menu>

有没有一种方法可以加载菜单 XML 在菜单下方显示自定义布局?有不同的想法吗?

【问题讨论】:

    标签: android android-layout navigation-drawer


    【解决方案1】:

    NavigationView 似乎不支持自定义页脚。在我的项目中,我根据其他一些 SO 答案制作了这个小怪物。

    <android.support.v4.widget.DrawerLayout
         android:id="@+id/drawer_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"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:background="@color/colorPrimary"
         android:fitsSystemWindows="true"
         tools:context=".ui.MainActivity">
    
        ...screen content...
    
        <android.support.design.widget.NavigationView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:fitsSystemWindows="true">
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="bottom"
                android:orientation="vertical">
    
                <RelativeLayout
                    android:layout_width="wrap_content"
                    android:layout_height="0dp"
                    android:layout_weight="1">
    
                    <android.support.design.widget.NavigationView
                        android:id="@+id/navigation_view"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="top"
                        app:elevation="0dp"
                        app:headerLayout="@layout/drawer_header"
                        app:menu="@menu/drawer">
                    </android.support.design.widget.NavigationView>
                    <View
                        android:layout_width="match_parent"
                        android:layout_height="21dp"
                        android:layout_alignParentBottom="true"
                        android:background="@drawable/bg_navbarscroll"/>
    
                </RelativeLayout>
    
                <include
                    android:id="@+id/premium_footer"
                    layout="@layout/drawer_footer"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"/>
            </LinearLayout>
        </android.support.design.widget.NavigationView>
    </android.support.v4.widget.DrawerLayout>
    

    我们这里有两个嵌套的 NavigationView。这可能有点矫枉过正,但我​​无法让它工作。这是基于这个问题中的工作,所以所有的功劳都在那里:How to add footer to NavigationView - Android support design library?

    真正的 NavView 是内部的,它有标题,有菜单,但它不适合系统窗口。第一个适合系统窗口并处理抽屉移动。您面临的问题是因为 ListView 不知道 NavView 中内容的大小。所以你需要确保没有任何东西在同一个布局中,所以没有重叠。您的 listView 必须在 NavView 父级的父级中。因为这可能会破坏 DrawerLayout 控件的机制,所以您需要第一个外部 NavigationView。

    或者,如果您可以在抽屉中不膨胀菜单的情况下生活,只需制作一个自定义的“老式”抽屉,就像 NavigationViews 出现之前的抽屉一样。

    【讨论】:

      【解决方案2】:

      就我而言,我想在抽屉底部添加一些信息文本。经过一番摆弄,我设法通过在NavigationView 中添加ConstraintLayout 来获得所需的结果:

          <androidx.drawerlayout.widget.DrawerLayout
              android:id="@+id/drawer_layout"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:fitsSystemWindows="true">
      
              <include
                  android:id="@+id/app_bar"
                  layout="@layout/app_bar_main"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent" />
      
      
              <com.google.android.material.navigation.NavigationView
                  android:id="@+id/nav_view"
                  android:layout_width="wrap_content"
                  android:layout_height="match_parent"
                  android:layout_gravity="start"
                  android:fitsSystemWindows="true"
                  app:headerLayout="@layout/nav_header_main"
                  app:menu="@menu/activity_main_drawer">
      
                  <androidx.constraintlayout.widget.ConstraintLayout
                      android:layout_width="match_parent"
                      android:layout_height="match_parent">
      
                      <TextView
                          android:id="@+id/bottom_content"
                          android:layout_width="wrap_content"
                          android:layout_height="wrap_content"
                          app:layout_constraintBottom_toBottomOf="parent"
                          app:layout_constraintEnd_toEndOf="parent"
                          app:layout_constraintStart_toStartOf="parent" />
      
                  </androidx.constraintlayout.widget.ConstraintLayout>
              </com.google.android.material.navigation.NavigationView>
      
      

      目前看来一切正常,但可能存在一些隐藏的陷阱。

      【讨论】:

        【解决方案3】:

        导航菜单中的固定(非滚动)页脚可以通过将 NavigationView 包裹在另一个布局周围来实现,就像您发布的那样。您可以安排它,使用 LinearLayout 作为页脚项目,如下所示:

        <android.support.design.widget.NavigationView
            android:id="@+id/drawer"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            app:headerLayout="@layout/drawer_header"
            app:menu="@menu/drawer">
        
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:clickable="true"
            android:orientation="vertical">
            <TextView
                android:id="@+id/footer_item_1"
                android:layout_width="match_parent"
                android:layout_height="48dp"
                android:gravity="center"
                android:text="Footer Item 1" />
            <TextView
                android:id="@+id/footer_item_2"
                android:layout_width="match_parent"
                android:layout_height="48dp"
                android:gravity="center"
                android:text="Footer Item 2" />
        </LinearLayout>
        

        你可以使用任何你想要的东西来代替 TextViews。有必要很好地构建底部布局以避免视图重叠。

        菜单 XML

        <menu xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:title="Communicate">
            <menu>
                <item
                    android:id="@+id/nav_share"
                    android:icon="@drawable/ic_menu_share"
                    android:title="Share" />
                <item
                    android:id="@+id/nav_send"
                    android:icon="@drawable/ic_menu_send"
                    android:title="Send" />
            </menu>
        </item>
        

        您终于可以在布局中添加 onclick 侦听器了

        View navFooter1 = findViewById(R.id.footer_item_1);
        navFooter1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Do footer action
            }
        });
        View navFooter2 = findViewById(R.id.footer_item_2);
        navFooter2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Do footer action
            }
        });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-08-18
          • 1970-01-01
          • 2015-08-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多