你需要传递什么参数给v4.widget.DrawerLayout.isDrawerOpen()/.openDrawer()/.closeDrawer()?

25

我一直在尝试将我的代码移植到 DrawerLayout 上,正如安卓 这里 所建议的,因为 SlidingDrawer 已经过时了。

我的问题是,到目前为止,DrawerLayout 似乎要么实现得非常糟糕,要么有着不太有帮助的错误信息(没有防御性编程),要么在文档中没有被很好地解释。

isDrawerOpen() 方法的描述可以在 这里 找到:

public boolean isDrawerOpen (View drawer)

检查给定的抽屉视图是否当前处于打开状态。要被认为是“打开的”,抽屉必须已经进入其完全可见的状态。要检查部分可见性,请使用 isDrawerVisible(android.view.View)。

参数:drawer - 要检查的抽屉视图

返回值:如果给定的抽屉视图处于打开状态,则为 true

每个方法isDrawerOpen(View drawer)openDrawer(View drawer)closeDrawer(View drawer)在传递以下内容时无法工作:所讨论的DrawerLayout或其任一子项。我不知道应该输入什么内容才能使它们正常运行。有人可以告诉我吗?
请参见下面的完整问题描述和实现。
我有一个如下的布局:
<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>

在我的代码中,我已经将以下方法与一个按钮连接起来:

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

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

然而,如果你将它本身作为参数传递(这是极其冗余的),你会收到以下错误提示:
E/AndroidRuntime(11241): java.lang.ClassCastException: 
android.widget.FrameLayout$LayoutParams cannot be cast to 
android.support.v4.widget.DrawerLayout$LayoutParams

(正如您所注意到的,它并没有告诉您哪里出了问题。这实际上是问题的症状)。
其他答案herehere要么难以理解,要么与问题密切相关而没有太多解释。即便如此,我还尝试添加一个伪造的LinearLayout或一个DrawerLayout的子元素,但每个都会给出错误:
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

有人能解释一下这些方法实际上需要传递什么参数才能正常工作吗?

4个回答

19

所以答案是:

需要传递给方法的是第二个子元素(也称为“Drawer”)。我的问题在于,当我弄清楚这一点时,我已经将布局简化到了最简单的实现以进行测试 - 我从“抽屉”中删除了重力。没有重力,你会得到上面完全不相关的错误信息。

我可以确认我使用以下设置使代码正常工作:

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

并且使用以下布局:

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

2
是的。如果您查看DrawerLayout的源代码,isDrawerOpen(...)方法会调用isDrawer(...)来检查传递给它的View是否为抽屉。标准是检查View是否具有Gravity.LEFTGravity.RIGHTlayout_gravity。 "start" layout_gravity是一个别名,可用于确定抽屉停靠的侧面。对于RTL(从右到左)语言,它将是Gravity.RIGHT,对于LTR语言,它是Gravity.LEFT。如果没有为View设置这些属性,则isDrawer(...)方法返回false。 - Squonk
1
谢谢你!在我的情况下,我对该使用哪个重力感到困惑。不是android:gravity而是android:layout_gravity - ruX
哇,这整个时间它都没能工作是因为我忘记了 layout_gravity。如果可以的话,加10分。 - Cullub

14

如果你想避免在调用 isDrawerOpen 时涉及到视图或布局的引用,可以采用另一种方法。

在这种情况下,你需要指定重力(Gravity):

mDrawerLayout.isDrawerOpen(Gravity.START);

mDrawerLayout作为您的DrawerLayout的引用。

正如您所说,不要忘记android:layout_gravity="start"


2

如果在您的 Activity 中有 DrawerLayout 的引用,并且在这种情况下具有 id 为 R.id.menuPane 的 FrameLayout,您还可以执行以下操作...

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

基本上,您需要传递对在DrawerLayout中用作抽屉的视图的引用,这将始终是mMenuPanel.getChildAt(1)。


-1

如果您正在使用支持库中的抽屉布局,正如我们从您的问题中所看到的那样,还有一个方法:

closeDrawers()

这将关闭所有打开的抽屉(通常只有一个)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接