What do you need to pass to v4.widget.DrawerLayout.isDrawerOpen()/.openDrawer()/.closeDrawer()
Asked Answered
E

4

25

I've been trying to move my code across to the DrawerLayout as suggested by android here as SlidingDrawer is deprecated.

My problem is that so far DrawerLayout seems to be either very badly implemented, has unhelpful error messages (no defensive programming) and/or isn't explained well enough in the documentation.

the isDrawerOpen() method is described here:

public boolean isDrawerOpen (View drawer)

Check if the given drawer view is currently in an open state. To be considered "open" the drawer must have settled into its fully visible state. To check for partial visibility use isDrawerVisible(android.view.View).

Parameters: drawer - Drawer view to check

Returns: true if the given drawer view is in an open state

Each of the methods isDrawerOpen(View drawer), openDrawer(View drawer) and closeDrawer(View drawer) don't work when passed: The DrawerLayout in question or either of it's children. I have no idea what I'm supposed to feed into these methods to allow them to function. Can someone let me know?

See below for entire problem description with implementation.

I have a layout like so:

<android.support.v4.widget.DrawerLayout
    android:id="@+id/mainmenuPanel"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:id="@+id/dualPane"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <FrameLayout
        android:id="@+id/menuPane"
        android:layout_width="300dp"
        android:layout_height="match_parent" />
</android.support.v4.widget.DrawerLayout>

And in my code I have the following method hooked up to a button:

protected void onCreate(Bundle savedInstanceState) {    
    ...
    mMenuPanel = (DrawerLayout) findViewById(R.id.mainmenuPanel);
    ....
}

public boolean isDrawerOpen() {
    if(mMenuPanel != null) {
        return mMenuPanel.isDrawerOpen(mMenuPanel);
    }
    return false;
}

However if you give it itself as an argument (which would be redundant in the extreme) you get the following error:

E/AndroidRuntime(11241): java.lang.ClassCastException: 
android.widget.FrameLayout$LayoutParams cannot be cast to 
android.support.v4.widget.DrawerLayout$LayoutParams

(Which as you'll notice, doesn't give you any information about what you did wrong. It is instead a symtom of the problem).

Other answers here or here are either incomprehensible or very closely tied to the question without much explanation. Even so I've tried adding a faux LinearLayout or one the DrawerLayouts children and each give this error:

E/AndroidRuntime(11424): java.lang.IllegalArgumentException: 
View android.widget.FrameLayout{420f5ea8 V.E..... ........ 
0,0-800,1172 #7f060038 app:id/menuPane} is not a drawer

Can anyone explain what these methods actually need to have passed to them to work?

Extensile answered 29/11, 2013 at 15:52 Comment(0)
E
19

And, the answer:

The second child (aka, the "Drawer") is what needs to be passed to the methods. My problem was that by the time I had figured that out I'd reduced the layout to as simple as possible implementation to test - I'd removed the gravity from the "drawer". Without a gravity, you get the above completely unrelated error messages.

I can confirm I got the code to work using the following setup:

mMenuPanel.isDrawerOpen(findViewById(R.id.drawer));

and with the layout:

<android.support.v4.widget.DrawerLayout
    android:id="@+id/mainmenuPanel"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <FrameLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <FrameLayout
        android:id="@+id/drawer"
        android:layout_width="300dp"
        android:layout_height="match_parent" 
        android:layout_gravity="start"/> <!-- This line was the problem!!!!!!!-->
</android.support.v4.widget.DrawerLayout>
Extensile answered 29/11, 2013 at 15:58 Comment(3)
Yes. If you look at the source for DrawerLayout, the isDrawerOpen(...) method makes a call to isDrawer(...) to check the View it's being passed is a drawer. The criteria is to check if the View has a layout_gravity of either Gravity.LEFT or Gravity.RIGHT. The "start" layout_gravity is an alias which can be used for determining which side the drawer is anchored. With RTL (right to left) languages it would be Gravity.RIGHT for LTR languages it's Gravity.LEFT. If none of those are set for the View, the isDrawer(..) method returns false.Stallings
Thank you man! In my case I was confused about which gravity to use. Not android:gravity but android:layout_gravity!Lefler
Wow, this whole time it wasn't working for me because I forgot the layout_gravity. +10 if I could.Merkle
R
14

if you want to avoid references to views or layouts in order to call isDrawerOpen, another way can be applied.

In this case you have to indicate the Gravity:

mDrawerLayout.isDrawerOpen(Gravity.START);

Being mDrawerLayout a reference to your DrawerLayout.

as you said, don't forget android:layout_gravity="start"

Rosenberger answered 11/4, 2014 at 10:51 Comment(0)
G
2

In your Activity if you have a reference to the DrawerLayout and in this case the FrameLayout with the id R.id.menuPane you can also do...

DrawerLayout mMenuPanel = (DrawerLayout) findViewById(R.id.mainmenuPanel);
FrameLayout mMenuPane = (FrameLayout) findViewById(R.id.menuPane);
mMenuPanel.isDrawerOpen(mMenuPane);

Basically you have to pass in a reference to the view being used as the drawer within the DrawerLayout, which will always be mMenuPanel.getChildAt(1) anyways.

Gratiana answered 23/1, 2014 at 22:19 Comment(0)
R
-1

If you are using the drawer layout from the support library as we can see from your question that you are, there is also the method:

closeDrawers()

This will close all open drawers (which is usually just the one).

Remarque answered 17/3, 2016 at 12:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.