实现滚动导航抽屉的最佳方式

Best way of implementing a scrolling navigation drawer

我一直在为我的一个应用程序添加导航抽屉,我开始想知道从使用 ListView 切换到多个 TextView 是否会更好导航抽屉列表项。查看 Google Design Guidelines on Navigation Drawer content (specifically the section on 'Scrolling'),我注意到多个 TextView 看起来会更好。

目前,我在导航抽屉中使用 ListViewImageView(它看起来有点像 this. However, when I scroll in my navigation drawer (I do this by turning my device landscape as there are not enough items in my list yet), only the ListView scrolls, and the ImageView stays as it is. I want it to be able to scoll more like this, where the ImageView is also scrolled with the ListView

此外,我发现我的导航抽屉中的 ListView 没有涟漪效应 as shown in this image,尽管我的其他 Activity 中的其他 ListViewFragment是的。

我面临的问题是什么,我该如何解决这些问题?

更新:

在Google的I/O应用程序(2014)中,navigation drawer layout底部似乎有一个LinearLayout,我认为它负责显示的项目列表。有人可以解释一下这是如何工作的吗?

only the ListView scrolls, and the ImageView stays as it is

听起来您的抽屉顶部有一个 ImageView,然后是一个 ListView。使用此配置,只有 ListView 会滚动(因为它是唯一可滚动的视图)。

您需要将 ImageView 添加为始终位于列表开头的 header。正如其中一条评论所建议的那样,做 listView.addHeaderView.

there seems to be a LinearLayout at the bottom of the navigation drawer layout which I think is responsible for the list of items shown. Could someone explain how this would work?

他们使用 LinearLayout 作为容纳所有 TextView 的容器:

private void createNavDrawerItems() {
    mDrawerItemsListContainer = (ViewGroup) findViewById(R.id.navdrawer_items_list);
    ...
    int i = 0;
    for (int itemId : mNavDrawerItems) {
        mNavDrawerItemViews[i] = makeNavDrawerItem(itemId, mDrawerItemsListContainer);
        mDrawerItemsListContainer.addView(mNavDrawerItemViews[i]);
        ++i;
    }
}

我相信他们使用 LinearLayout 并以编程方式膨胀所有项目的原因是能够轻松使用分隔项目:

private View makeNavDrawerItem(final int itemId, ViewGroup container) {
    ...
    if (itemId == NAVDRAWER_ITEM_SEPARATOR) {
        layoutToInflate = R.layout.navdrawer_separator;
    } else if (itemId == NAVDRAWER_ITEM_SEPARATOR_SPECIAL) {
        layoutToInflate = R.layout.navdrawer_separator;
    } else {
        layoutToInflate = R.layout.navdrawer_item;
    }
    ...
    return view;
}

ListView 中,您必须创建一个单独的项目类型并在那里使用分隔线的布局,这可能会变得更加麻烦。

乍一看,然而,这段代码似乎只是re-inventing轮子,因为所有这些都可以通过ListView.

截至 2015 年 5 月 29 日(在 Google I/O 2015 之后),您可以使用 Android 设计支持库 添加一个NavigationView to your app(s). The Android Developer Blogspot article 说明如下:

Navigation View

The navigation drawer can be an important focal point for identity and navigation within your app and consistency in the design here can make a considerable difference in how easy your app is to navigate, particularly for first time users. NavigationView makes this easier by providing the framework you need for the navigation drawer as well as the ability to inflate your navigation items through a menu resource.

...

You can then start using the Design library with a single new dependency:
compile 'com.android.support:design:22.2.0'

...

The Design library, AppCompat, and all of the Android Support Library are important tools in providing the building blocks needed to build a modern, great looking Android app without building everything from scratch.

使用 android.support.v4.widget.DrawerLayout 和 NavigationView 实现可滚动的导航抽屉可能比在以下位置描述的更简单:http://android-developers.blogspot.ru/2015/05/android-design-support-library.html

该文章建议将应用程序导航抽屉的每个元素添加为菜单项。这很酷,对于大多数开发人员来说绝对是一种可行的方法。 但是,如果您已经在内部实现了导航抽屉怎么办?线性布局?

看来您可以轻松地使旧的良好布局可滚动:只需将其设置为 NavigationView 的 "app:headerLayout"。无需更多更改! 因此,在最终解决方案中,您将拥有:

您的 Activity 的布局,类似于上面的博客 post,但没有 "app:menu="@menu/drawer" 属性,例如:

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <!-- your content layout -->

    <android.support.design.widget.NavigationView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/drawer_header"
        />
</android.support.v4.widget.DrawerLayout>

以及 "drawer_header.xml" 文件中所有旧抽屉内容的布局,迁移时没有对这个可滚动的抽屉进行任何更改,例如这个:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:choiceMode="singleChoice"
    android:orientation="vertical">

    <TextView
        android:id="@+id/myFirstButton"
        android:onClick="onMyFirstButtonClick"
        android:text="@string/my_first_button_title"/>

    <TextView
        android:id="@+id/goToTheTopButton"
        android:onClick="onGoToTheTopButtonClick"
        android:text="@string/go_to_the_top_title"/>

    <View style="@style/Divider"/>

    <!-- Some other "menu items" -->
</LinearLayout>

有关完整的工作示例,请参阅此 activity 布局:https://github.com/andstatus/andstatus/blob/master/app/src/main/res/layout/timeline.xml and this commit, where I migrated to a scrollable Navigation Drawer: https://github.com/andstatus/andstatus/commit/a80b299de714bdd65cacb138ffb31adc3ea23a98