【问题标题】:Navigation Drawer: Add Titles to Groups, Not Items导航抽屉:将标题添加到组,而不是项目
【发布时间】:2016-04-11 07:25:16
【问题描述】:

我有一个标准的导航抽屉,由 Android Studio 预先创建,并希望用多个组填充它。我从这个开始:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_mode_person"
            android:icon="@drawable/ic_person_black_24dp"
            android:title="Person" />
        <item
            android:id="@+id/nav_mode_group"
            android:icon="@drawable/ic_group_black_24dp"
            android:title="Community" />
    </group>

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

但我没有得到的是是否可以给每个组一个标题?我的意思是&lt;item&gt;s 有一个android:title 选项,但&lt;group&gt;s 不可用,如果我尝试将组包裹在项目周围,我得到的是一个混乱的条目行为。

我通读了 Google 关于导航抽屉的设计指南,但错过了组应该有自己的名称还是不应该有自己的名称。这是我想要实现的图片:

是否可以不添加随机&lt;TextView&gt;s?顺便说一句,我想通过 XML 来实现,而不是通过编程方式。

【问题讨论】:

标签: android material-design navigation-drawer


【解决方案1】:

你是对的,不可能给组一个标题。唯一的选择似乎是将组包装到 &lt;item&gt;&lt;menu&gt; 这样的标签中

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:title="General">
        <menu>
            <group android:checkableBehavior="single">
                <item
                    android:id="@+id/nav_camera"
                    android:icon="@drawable/ic_menu_camera"
                    android:title="Import" />
                <item
                    android:id="@+id/nav_gallery"
                    android:icon="@drawable/ic_menu_gallery"
                    android:title="Gallery" />
            </group>
        </menu>
    </item>

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

产生这样的导航抽屉菜单

【讨论】:

  • 我试过了,但不幸的是,如果您尝试在活动创建时以编程方式检查某些项目,事情会变得一团糟。当以这种方式设置项目预检查时(例如Import),如果用户点击不同的项目(Gallery),则第一个保持选中状态。用户还应多次点击ImportGallery 以取消选中第一个条目。这就是我拒绝此解决方法的原因。
  • 你最初没有写过这个,所以没有理由拒绝我的回答。如果checkableBehavior 组对您不起作用,那么您必须以编程方式进行。检查选定的item 并取消选中所有其他活动创建和每个项目点击。
  • 其实我写过,但没有详细说明:if I try to wrap groups around items, what I get is a messy entries behavior。否决票是合法的,因为您的回答完全忽略了这一点。
  • @Saenic 这正是我想要的,谢谢!我的另一个问题是我想动态隐藏/取消隐藏菜单项,这是我使用 menuItem.setVisible(true); 实现的。但它不适用于另一个项目内的项目,例如上面示例中的 Import。我该如何实现这一点?
  • @Neha 我在将项目设置为可见/不可见时遇到了同样的问题。我需要在菜单上使用findItem(),而不是遍历所有项目(没有找到嵌套项目)。
【解决方案2】:

您还需要有一个带有android:checkableBehavior="single" 的外部组,这样就不会从First Category 中选择两个项目,而从Second Category 中选择其他项目。这是工作代码。

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
    android:title="First Category">
    <menu>
        <group
            android:id="@+id/menu_top"
            android:checkableBehavior="single">
            <item
                android:id="@+id/id1"
                android:icon="@drawable/drawable1"
                android:title="Title1" />

            <item
                android:id="@+id/id2"
                android:icon="@drawable/drawable2"
                android:title="Title2" />
        </group>
    </menu>
</item>
<item
    android:title="Second Category">
    <menu>
        <group
            android:id="@+id/menu_bottom"
            android:checkableBehavior="single">
            <item
                android:id="@+id/id3"
                android:icon="@drawable/drawable3"
                android:title="Title3" />

            <item
                android:id="@+id/id4"
                android:icon="@drawable/drawable4"
                android:title="Title4" />
        </group>
    </menu>
</item>
</group>
</menu>

【讨论】:

  • 为什么第一个分类不能点击了?我使用了这个例子,看起来很漂亮,正是我想要的。我的导航抽屉中最多有四个类别,现在只有一个类别中的项目是可点击的。我试着玩android:checkableBehavior="single",在不同的地方分组移动、删除和粘贴,但没有成功,只有一个类别是可点击的菜单项。有任何想法吗?非常感谢!
【解决方案3】:

这里很好地定义了如何创建菜单。

http://developer.android.com/guide/topics/ui/menus.html

因此,在您的情况下,在此订单项->菜单->组中创建您的列表。也就是说:

 <item android:title="Title">
     <menu>
         <group android:checkableBehavior="single">
             <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" />
                .   .   .
                .   .   . 

【讨论】:

  • 我在@Saenic 的答案的评论中描述了同样的问题。
【解决方案4】:

添加xml类navigation_drawer_title:

<?xml version="1.0" encoding="utf-8"?>
<TextView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:text="communicate"
        android:layout_height="wrap_content"/>

并像这样更改您的navigationAdapter

private static final int TYPE_HEADER = 0; 
    private static final int TYPE_ITEM = 1;
    private static final int TYPE_SEPARATOR = 2;
    private static final int TYPE_TITLE = 3;
    @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
        {
            View v = null;
            switch (viewType)
            {
                case TYPE_HEADER:
                    v = LayoutInflater.from(parent.getContext()).inflate(R.layout.navigation_drawer_header, parent, false); //Inflating the layout
                    break;
                case TYPE_ITEM:
                    v = LayoutInflater.from(parent.getContext()).inflate(R.layout.navigation_drawer_item, parent, false); //Inflating the layout
                    break;
                case TYPE_SEPARATOR:
                    v = LayoutInflater.from(parent.getContext()).inflate(R.layout.navigation_drawer_separator, parent, false); //Inflating the layout
                    break;

                case TYPE_TITLE:
                    v = LayoutInflater.from(parent.getContext()).inflate(R.layout.navigation_drawer_title, parent, false); //Inflating the layout
                    break;
            }
            return new ViewHolder(v, viewType); // Returning the created object

        }

@Override
    public int getItemViewType(int position)
    {
        if (position == 0)
            return TYPE_HEADER;
        if (navMenuItems.get(position - 1).getItemType() == NavItemType.Group)
            return TYPE_SEPARATOR;
        if (navMenuItems.get(position - 2).getItemType() == NavItemType.Group)
            return TYPE_TITLE

        return TYPE_ITEM;
    }

【讨论】:

  • 我在我的问题中说过,我不想尝试以编程方式解决这个问题。
  • 我不知道。我只是在适配器中完成的。
【解决方案5】:

对于那些仍在苦苦挣扎的人来说。特别是在 DrawerLayout + Jetpack Navigation 上。我要放弃我自己的实现。在弄乱了菜单、NavigationView 和 Jetpack Navigation 之后。只需对抽屉导航进行基本设置,然后将此菜单用作“命名组”的NavigationView 菜单。

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:showIn="navigation_view">

    <!-- Group for menu item without title -->
    <group android:checkableBehavior="single">
        <item
            android:id="@+id/yourFragment1"
            android:title="Fragment 1"/>
    </group>


    <item android:title="Group 1">
        <menu>
            <group
                android:checkableBehavior="single">
                <item
                    android:id="@+id/yourFragment2"
                    android:title="Fragment 2"/>

                <item
                    android:id="@+id/yourFragment3"
                    android:title="Fragment 3"/>
            </group>
        </menu>
    </item>

    <item android:title="Group 2">
        <menu>
            <group
                android:checkableBehavior="single">
                <item
                    android:id="@+id/yourFragment4"
                    android:title="Fragment 4"/>

                <item
                    android:id="@+id/yourFragment5"
                    android:title="Fragment 5"/>

                <item
                    android:id="@+id/yourFragment6"
                    android:title="Fragment 6"/>
            </group>
        </menu>
    </item>
</menu>

您还可以添加导航到另一个片段以外的选项,例如注销选项。就像下面一样。

navigationView.setNavigationItemSelectedListener { dest ->

    if (dest.itemId == R.id.yourMenuIdOfLogoutInMenuXML) {
        logoutUser();
    } else {
        // This will navigate to a corresponding fragments
        NavigationUI.onNavDestinationSelected(dest, navController)

        // drawerLayout is reference to DrawerLayout widget component
        drawerLayout.closeDrawer(GravityCompat.START)
    }

    true
}

如果你想以编程方式检查某个菜单,你可以调用

// navigationView is a reference to your NavigationView component.
navigationView.setCheckedItem(R.id.idOfMenuThatYouWantToCheck)

PS。对于那些不知道如何使用 Jetpack Navigation 设置 DrawerLayout 的人,请参阅此示例Setup Jetpack Navigation with DrawerLayout

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多