Best way of implementing a scrolling navigation drawer
Asked Answered
M

3

9

I have been adding a navigation drawer to one of my apps, and I started to wonder whether or not it would be better to switch from using a ListView to multiple TextViews for the navigation drawer list items. Looking at the Google Design Guidelines on Navigation Drawer content (specifically the section on 'Scrolling'), I noticed that it may look nicer with multiple TextViews.

At the moment, I am using a ListView and ImageView in my navigation drawer (it looks a little like 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.

Additionally, I found that my ListView in my navigation drawer does not have the ripple effects as shown in this image although other ListViews in my other Activitys and Fragments do.

What are the issues I am facing and how could I go about resolving these?

Update:

In Google's I/O App (2014), 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?

Mopey answered 6/5, 2015 at 18:14 Comment(12)
Please, post anycode for a better help.Venezuela
@SiloéBezerraBispo I don't really see a need to post code for this scenario, but if you insist, what code exactly should I add on to my question?Mopey
I don't see a problem using TextViews (presumably inside a ScrollView) instead of a ListView if the navigation items are known in advance and not determined dynamically. Alternatively, you could add the image as a header view on the ListView.Allsopp
@Allsopp How would I go about adding the image as a header view on the ListView?Mopey
ListView.addHeaderViewAllsopp
Thanks, I will try this when I get home...Mopey
@Allsopp This works, but how would I be able to use dividers as shown here if I use one ListView with a header view?Mopey
Also, in Google's I/O App, there seems to be a LinearLayout at the bottom of the navigation drawer which I think is responsible for the list of items shown. Could someone explain how this works?Mopey
Check my code here you will got your all answer, but you have to spend sometime: github.com/dhaval0122/ActionBar-Navigation-TabsWald
@DhawalSodhaParmar I have had a look at your answer and was wondering what the ScrimInsetsScrollView is, as defined in this layout file.Mopey
Its custom class used to draw components like overlay action bar, navigation bar for (>= API 21).Wald
github.com/neokree/MaterialNavigationDrawer/blob/master/… this library does exactly what you need.Tybie
L
4

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

It sounds like your drawer contains an ImageView at the top and then a ListView follows. With this configuration only the ListView will scroll (because it's the only view that's scrollable).

You need to add the ImageView as a header which is always at the beginning of the list. As one of the comments suggested, do 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?

They use the LinearLayout as a container to hold all the TextViews:

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

I believe the reason they use a LinearLayout and inflate all the items programmatically is to be able to use separator items easily:

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

In a ListView you'd have to create a separate item type and use the divider's layout there, which could possibly get more cumbersome.

At first glance, however, this code just seems to be re-inventing the wheel as all of this is possible with a ListView.

Lainelainey answered 17/5, 2015 at 17:23 Comment(5)
I like the idea of having TextViews shown in your answer mainly because I would be able to add separators and have more control over my layout.Mopey
You don't need to add individual separator views. LinearLayout can draw dividers between its children, just give it a drawable and call 'setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);`Allsopp
Thank you for your answer. I will see if I can implement the navigation drawer in this way into my app.Mopey
@Lainelainey Where could I find the code you've posted (is it from Google's I/O app on GitHub)?Mopey
@FarbodSalamat-Zadeh yes it's from repository whose link you've provided. BaseActivity contains createNavDrawerItems method.Lainelainey
M
0

As of 29th May 2015 (after Google I/O 2015), you can use the Android Design Support Library to add a NavigationView to your app(s). The Android Developer Blogspot article states the following:

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.

Mopey answered 6/6, 2015 at 1:54 Comment(3)
But is the NavigationView scrollable as asked in the question?Spongioblast
I suppose it could be placed inside a ScrollView if necessary.Mopey
Placing it inside a scrollview causes problem when I call DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); drawer.closeDrawer(GravityCompat.START); in the onClick of the menu items. The error was no Drawer found.Dressel
E
0

Implementing scrollable Navigation Drawer using android.support.v4.widget.DrawerLayout and NavigationView could be even simpler than it is described at: http://android-developers.blogspot.ru/2015/05/android-design-support-library.html

That article suggests adding each element of your application's Navigation Drawer as a Menu Item. This is cool and definitely a way to go for most of developers. But what if you already has a Navigation Drawer implemented inside e.g. Linear Layout?

It appears that you can easily make your old good layout scrollable: just set it as a "app:headerLayout" of the NavigationView. No more changes are needed! So, in a final solution you will have:

A layout of your Activity, similar to the above blog post, but without an "app:menu="@menu/drawer" attribute e.g. this:

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

And a layout for all your old Drawer content in the "drawer_header.xml" file, migrated without any changes to this scrollable Drawer, E.g. this:

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

For full working example see this activity layout: 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

Est answered 28/8, 2016 at 12:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.