Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 754
Graeme Avatar asked Nov 29 '13 15:11

Graeme


3 Answers

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>
like image 92
Graeme Avatar answered Nov 06 '22 18:11

Graeme


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"

like image 44
Jose M Lechon Avatar answered Nov 06 '22 18:11

Jose M Lechon


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.

like image 2
speedynomads Avatar answered Nov 06 '22 20:11

speedynomads