mikepenz / MaterialDrawer

The flexible, easy to use, all in one drawer library for your Android project. Now brand new with material 2 design.
https://mikepenz.dev
Apache License 2.0
11.67k stars 2.05k forks source link

Drawer under Action Bar #930

Closed rsd-raul closed 8 years ago

rsd-raul commented 8 years ago

First of all, brilliant library... It's so simple and intuitive you just want to find new uses for it.

Now to the problem...

I'm trying to add a second drawer, this time under the ActionBar, sadly I haven't got it to work. I have tried separately:

.withRootView(R.id.coordinatorDashboard)
.withRootView(R.id.viewpager)

In this my code:

mRightDrawer = new DrawerBuilder()
                .withActivity(this)
                .withDisplayBelowStatusBar(true)
                // .withToolbar(mToolbar)
                // .withActionBarDrawerToggle(true)
                // .withActionBarDrawerToggleAnimated(true)
                .withCloseOnClick(false)
                .addDrawerItems(
                        mainSection,
                        item1, item2, item3
                        listSection,
                        list1, list2, list3
                )
                .withDrawerGravity(Gravity.END)
                .build();`
<android.support.design.widget.CoordinatorLayout
    android:id="@+id/coordinatorDashboard"
    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"
    tools:context=".MainActivity">

    <android.support.design.widget.AppBarLayout style="@style/appBarLayout" >

        <android.support.v7.widget.Toolbar style="@style/toolbar"
            android:id="@+id/toolbar" />

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

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

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

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

With viewpager it just goes bananas... With coordinator things get weird:

screenshot_2016-01-13-08-12-03 1

I just removed:

.withToolbar(mToolbar)
.withActionBarDrawerToggle(true)
.withActionBarDrawerToggleAnimated(true)

As the menu then triggers the second drawer instead of the first... Nothing changes regarding "under the actionbar" thought.

Also... Is there a way to force the drawer to open ONLY with:

mRightDrawer.openDrawer();
rsd-raul commented 8 years ago

Just tried:

<!-- the layout which will contain (host) the drawerLayout -->
    <FrameLayout
        android:layout_below="@id/toolbar"
        android:id="@+id/drawer_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!-- the layout which will be the content of the activity (which will be hosted inside the drawer (NOT the list of the drawer)) -->
        <FrameLayout
            android:id="@+id/frame_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

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

        </FrameLayout>
    </FrameLayout>

As it is the example: https://github.com/mikepenz/MaterialDrawer/blob/develop/app/src/main/java/com/mikepenz/materialdrawer/app/CustomContainerActivity.java https://github.com/mikepenz/MaterialDrawer/blob/develop/app/src/main/res/layout/activity_sample_custom_container_dark_toolbar.xml

Nothing changes, same behaviour.

mikepenz commented 8 years ago

@rsd-raul you try to add a second drawer. That means 2 drawer in one activity?

You have an activity with a collapsing toolbar and want the drawer to be below the toolbar?

Regarding only allow to open the drawer via mRightDrawer.openDrawer(); --> "LOCK" the drawer (this can be done via the DrawerLayout)

rsd-raul commented 8 years ago

Yes, two drawers, one activity. The main drawer on the left, controlled by the ActionBar and gesture, and the one on the right, toggled only by a button.

And indeed the Toolbar collapses only to leave TabLayout at sight :S

Ps: Locked with DrawerLayout :+1:

mikepenz commented 8 years ago

@rsd-raul can you probably just have one DrawerLayout which will have both drawers? As the MultiDrawer sample showcases? There is one limitation with this that you can't have one drawer below the toolbar and the other under the toolbar. You may be able to add a padding to the right drawer so it looks that it starts below the toolbar but this will add a dark layer above the non drawer areas (this is DrawerLayout and i can't change this)

rsd-raul commented 8 years ago

I'm sorry to hear that, but to be fair... It's way to specific, is normal that DrawerLayout doesn't contemplate the option. I think having the second one under the Status Bar will do more than fine :D

I will consider to switch .build() to .append(result), I'm gessing having both in the same DrawerLayout its much more efficient, the problem is I would have to remove the LOCK on the DrawerLayout in order to be able to open the main with a gesture...

...Which right now doesn't seem so bad, but it also generates some random behavior:

I set my LeftDrawer at my onCreate method, but my RightDrawer only if the user selects the option on the ActionBar, which results in:

aaa

And can be corrected by the user by opening the Main Drawer (left) and making click on any Icon.

bbb

Or programmatically, by not initializing the Second Drawer (right) on a button, but onCreate. Which might be computationally costly depending on what you are doing there :S

I think I'll try to make the setup as light as posible and then use .append and onCreate for both Drawers.

mikepenz commented 8 years ago

@rsd-raul you can also define the LOCK for a specific gravity http://developer.android.com/reference/android/support/v4/widget/DrawerLayout.html#setDrawerLockMode(int, int)

Regarding how expensive. That's not too much for the right drawer, as it is basically just a RecyclerView which will be filled with items. And defining the correct paddings.

rsd-raul commented 8 years ago

Perfect, now I'm using:

mFilterDrawer.getDrawerLayout().setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, GravityCompat.END);`

To block the right one... Though, I'm missing the possibility to add an OnDrawerListener to the Drawer after the creation in order to activate the gestures once opened and disable them at.

I tried with almost successfully with:

mFilterDrawer.getDrawerLayout().setDrawerListener(new Drawer.OnDrawerItemClickListener() {
    ...
}

But as they are now sharing a common DrawerLayout things get messy... So I would just leave it like it is, maybe in the future you have time to add that as a feature (if it's even posible).

I don't think it's necessary, as it's not a common "use case", but well... If you do I'll be using it :D

Many thanks again for an outstanding library, everything is incredibly well thought.

Ps: I have a couple of extra questions, but I'm gonna do some research first in order to save you the extra hazle. And as they are not related to this one, it's probably better to isolate them for people to find in the future.

mikepenz commented 8 years ago

@rsd-raul i'm not quite sure what you mean that you miss the possibility to add an OnDrawerListener to the drawer after creation.

The code you padded mixes up the DrawerListener and the OnDrawerItemClickListener. You can provide a different OnDrawerItemClickListener for each of the two drawers. The left (main) one, and the right (appended) one.

You are right that there is only one OnDrawerListener which you set via .withOnDrawerListener(new Drawer.OnDrawerListener() { on the left (main) drawer via it's builder. But this will provide a View with the event, which you can check if it is the left or right drawer.

.withOnDrawerListener(new Drawer.OnDrawerListener() {
                    @Override
                    public void onDrawerOpened(View drawerView) {
                        if (drawerView == result.getSlider()) {
                            Log.e("sample", "left opened");
                        } else if (drawerView == resultAppended.getSlider()) {
                            Log.e("sample", "right opened");
                        }
                    }

                    @Override
                    public void onDrawerClosed(View drawerView) {
                        if (drawerView == result.getSlider()) {
                            Log.e("sample", "left closed");
                        } else if (drawerView == resultAppended.getSlider()) {
                            Log.e("sample", "right closed");
                        }
                    }

                    @Override
                    public void onDrawerSlide(View drawerView, float slideOffset) {

                    }
                })

This should do the thing you want to achieve.

Ok great :) thanks a lot for this :)

Just let me know. I may be faster answering them, or hinting you into the correct direction then you can search for them :P

rsd-raul commented 8 years ago

The problem with the onDrawerListener in my case it's the content, as I'm calling a function of the object I'm creating...

...Wait, I just realise that might actually work, the drawer will be initialized but not opened, so the mFilterDrawer will be null at creation but not short after in response to a button click.

Mmmmmm still nothing, probably sleep deprivation kicking in, I'm using this code for the Right Drawer:

mFilterDrawer = new DrawerBuilder()
                .withActivity(this)
                .withDisplayBelowStatusBar(true)
                .withCloseOnClick(false)
                .addDrawerItems(
                        mainSection,
                        item1, item2, item3
                        listSection,
                        list1, list2, list3
                )
                .withOnDrawerListener(new Drawer.OnDrawerListener() {
                    @Override
                    public void onDrawerOpened(View drawerView) {
                        Log.d("myApp", "testOpened");
                        mFilterDrawer.getDrawerLayout().setDrawerLockMode(
                                DrawerLayout.LOCK_MODE_UNLOCKED);
                    }

                    @Override
                    public void onDrawerClosed(View drawerView) {
                        Log.d("myApp", "testClosed");
                        mFilterDrawer.getDrawerLayout().setDrawerLockMode(
                                DrawerLayout.LOCK_MODE_LOCKED_CLOSED, GravityCompat.END);
                    }

                    @Override
                    public void onDrawerSlide(View drawerView, float slideOffset) { }
                })
                .withDrawerGravity(Gravity.END)
                .append(mDrawer);

// Locked after creation
mFilterDrawer.getDrawerLayout().setDrawerLockMode(
                DrawerLayout.LOCK_MODE_LOCKED_CLOSED, GravityCompat.END);

Curiously it never enters onDrawerOpened or onDrawerClosed, I though it will detect only gestures and then I tried to unlocked it onClick:

if(mFilterDrawer == null)
                    setupFilterDrawer();

                mFilterDrawer.openDrawer();

                mFilterDrawer.getDrawerLayout().setDrawerLockMode(
                        DrawerLayout.LOCK_MODE_UNLOCKED);

But still never reaches onDrawerClosed... Which is odd, as it should Log no mather what drawer is being opened/closed.

SOLUTION: Being append instead of built seems to discard the OnDrawerListener of the appended one, as setting the same method on mDrawer does the job wonderfully. :+1:

Ps: I did mixed OnDrawerListener with OnDrawerItemClickListener... That explains a lot xD

About the questions, the multi-selection of values... Which I have read already it's not supported. So as recommended changing color/background/etc will do.

And well, I would like to change the right drawer width, but my tries were unsuccesful and it wasn't really necesary, I just though it would be cool xD

mikepenz commented 8 years ago

@rsd-raul regarding the first part. yes the OnDrawerListener is only set via the main DrawerBuilder as this one manages the DrawerLayout and can be seen as the master. As many functions are the same i have kept the appended drawer in the same object, which may cause confusion as not all methods will do what they do when used via the master DrawerBuilder.

Yeah :D

Regarding Multi-Selection :D that will come in v5.0.0 where already a first beta is out. MultiSelect not yet enabled. (But is theoretically already in via the FastAdapter https://github.com/mikepenz/FastAdapter)

withWidthDp doesn't do the job?

rsd-raul commented 8 years ago

You sure know your code... It does, I don't know how I missed that.

Well, probably because sometimes I mix "height" and "width" while programming, to many things to do at the same time, you should see half the code code commented in Spanish and half in English xD

Once again, thanks for everything, I guess I'll wait for v5.0.0 and in the meantime, close this Issue :D

mikepenz commented 8 years ago

@rsd-raul great :). have a nice evening

mikepenz commented 8 years ago

@rsd-raul i just enabled multiSelection within the latest beta of the MaterialDrawer you can get it here: https://github.com/mikepenz/MaterialDrawer/issues/920#issuecomment-171478069

I would really love to get some feedback, because MultiSelection within the drawer is a complicated topic, as it does not really follow normal multiSelection rules which are common in lists

rsd-raul commented 8 years ago

Perfect, as soon as I start the filter development I'll make sure to check it out :+1:

By the way Mike, is there a way to scroll the drawer to a certain Item/Identifier??

I'm using 3 expandable items which will contain X items each, and currently after expanding a list (depending on the position) the user have to scroll to see the content.. Which is not ideal :S

mikepenz commented 8 years ago

you can get the position of an item. you may be able to scroll to this position via the RecyclerView then. I assume you will find enough resources on StackOverflow to scroll to a position if you know the index.

oliverbob commented 7 years ago

Hi Mike, how do I achieve disabling/locking the left drawer in the multidrawer and enable/unlock only the right drawer?

DrawerLayout drawerLayout = result.getDrawerLayout(); drawerLayout.setDrawerLockMode(LOCK_MODE_LOCKED_CLOSED);

locks both of the drawer.

mikepenz commented 7 years ago

just pass the view which you want to lock to the method: https://developer.android.com/reference/android/support/v4/widget/DrawerLayout.html#setDrawerLockMode(int, android.view.View)

kennyung6 commented 7 years ago

@mikepenz. Thanks for this great library, its indeed helpful. Please i have a similar case but mine is slightly different from op's. my headache is that i can't figure out how to make the cross fade drawer layout show behind the ActionBar/APP Bar. I tried using

.withDrawerLayout(R.layout.crossfade_drawer).withRootView(R.id.miniDrawer).withRootView(R.id.drawer_container) But i was getting: "Relative layout" cannot be cast into drawerlayout.

Below is my cross fade drawerlayout.xml

`<RelativeLayout 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:id="@+id/miniDrawer" android:fitsSystemWindows="true" android:gravity="center">

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    android:elevation="4dp"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
  <!-- the layout which will contain (host) the drawerLayout -->
    <FrameLayout
        android:id="@+id/drawer_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/toolbar">

<com.mikepenz.crossfadedrawerlayout.view.CrossfadeDrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/material_drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true" />

    </FrameLayout>

`

Regards