Что вам нужно передать в v4.widget.DrawerLayout.isDrawerOpen()/.openDrawer()/.closeDrawer()

Я пытался переместить свой код на DrawerLayout, как это было предложено андроидом здесь, так как SlidingDrawer устарело.

Моя проблема в том, что до сих пор DrawerLayout либо очень плохо реализована, имеет бесполезные сообщения об ошибках (нет защитного программирования) и/или недостаточно хорошо объяснено в документации.

метод isDrawerOpen() описан здесь :

public boolean isDrawerOpen (ящик просмотра)

Проверьте, находится ли данный вид ящика в настоящее время в открытом состоянии. Чтобы считаться «открытым», ящик должен находиться в полностью видимом состоянии. Чтобы проверить частичную видимость, используйте isDrawerVisible(android.view.View).

Параметры: ящик - вид ящика для проверки

Возвращает: 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

(Что, как вы заметите, не дает вам никакой информации о том, что вы сделали неправильно. Вместо этого это симптом проблемы).

Другие ответы здесь или здесь либо непонятны, либо очень тесно связаны с вопросом без особых объяснений. Несмотря на это, я пытался добавить поддельный LinearLayout или один из дочерних элементов DrawerLayouts, и каждый из них выдавал эту ошибку:

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

Кто-нибудь может объяснить, что эти методы на самом деле должны были передать им, чтобы они работали?


person Graeme    schedule 29.11.2013    source источник


Ответы (4)


И, ответ:

Второй дочерний элемент (также известный как «Ящик») — это то, что нужно передать методам. Моя проблема заключалась в том, что к тому времени, когда я понял это, я сократил макет до максимально простой реализации для тестирования - я удалил гравитацию из «ящика». Без гравитации вы получите приведенные выше совершенно не связанные сообщения об ошибках.

Я могу подтвердить, что код работает, используя следующую настройку:

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>
person Graeme    schedule 29.11.2013
comment
Да. Если вы посмотрите на источник для DrawerLayout, метод isDrawerOpen(...) вызывает isDrawer(...), чтобы проверить, что View, который он передает, является ящиком. Критерий состоит в том, чтобы проверить, имеет ли View layout_gravity либо Gravity.LEFT, либо Gravity.RIGHT. Начало layout_gravity — это псевдоним, который можно использовать для определения стороны, на которой ящик закреплен. Для языков RTL (справа налево) это будет Gravity.RIGHT, для языков LTR это Gravity.LEFT. Если ни один из них не установлен для View, метод isDrawer(..) возвращает false. - person Squonk; 29.11.2013
comment
Спасибо, мужик! В моем случае я был смущен тем, какую гравитацию использовать. Не android:gravity, а android:layout_gravity! - person ruX; 27.07.2014
comment
Ничего себе, все это время у меня не работало, потому что я забыл layout_gravity. +10, если бы я мог. - person Cullub; 13.04.2018

если вы хотите избежать ссылок на представления или макеты для вызова isDrawerOpen, можно применить другой способ.

В этом случае вы должны указать Gravity:

mDrawerLayout.isDrawerOpen(Gravity.START);

Быть mDrawerLayout ссылкой на ваш DrawerLayout.

как ты сказал, не забудь android:layout_gravity="start"

person Jose M Lechon    schedule 11.04.2014

В вашей деятельности, если у вас есть ссылка на DrawerLayout и в этом случае FrameLayout с идентификатором R.id.menuPane, вы также можете сделать...

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

По сути, вам нужно передать ссылку на представление, используемое в качестве ящика в DrawerLayout, которое в любом случае всегда будет mMenuPanel.getChildAt(1).

person speedynomads    schedule 23.01.2014

Если вы используете макет ящика из библиотеки поддержки, как мы видим из вашего вопроса, есть также метод:

closeDrawers()

Это закроет все открытые ящики (обычно только один).

person 34m0    schedule 17.03.2016