Android Navigation Drawer и windowActionBarOverlay = true

Я пытаюсь реализовать новый Android Navigation Drawer в своем приложении. Я создал BaseActivity.java, который управляет настройкой Drawer и прослушивателями, и у меня есть две подактивности, которые расширяют этот базовый класс. Во втором упражнении я планирую использовать другой стиль панели действий, используя следующие атрибуты:

<item name="android:windowActionBarOverlay">true</item>
<item name="android:background">@android:color/transparent</item>

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

Я добился именно этого, но теперь проблема в том, что, поскольку содержимое расширяется, чтобы использовать дополнительное пространство с использованием ActionBar в качестве наложения, сам Navigation Drawer тоже расширяется и перекрывает ActionBar, создавая довольно ужасное внешний вид макета:

введите здесь описание изображения

Что я хотел бы сделать, так это фактическое содержимое (макет кадра, который будет заполнен фрагментом), чтобы занимать дополнительное пространство, но чтобы панель навигации по-прежнему находилась под панелью действий, как в приложении Play Music:

введите здесь описание изображения

Любые идеи о том, что я могу сделать, чтобы это произошло?

EDIT Итак, с помощью Ахмада я установил marginTop только в ListView. Вот макет:

<!-- The navigation drawer -->
<ListView android:id="@+id/left_drawer"
          android:layout_marginTop="?android:attr/actionBarSize"
<!-- This was added after seeing the crazy effect, but does nothing -->
          android:layout_marginBottom="0dp"
          android:layout_marginLeft="0dp"
          android:layout_marginRight="0dp"
          android:layout_width="240dp"
          android:layout_height="fill_parent"
          android:layout_gravity="start"
          android:choiceMode="singleChoice"
          android:background="?attr/listviewBackground"
          />

И теперь это отлично работает для верхней стороны, но по какой-то причине внизу представления также есть поле, что для меня вообще не имеет никакого смысла. Снимок экрана.

Не знаю, чем это вызвано :(


person daniel_c05    schedule 30.05.2013    source источник
comment
Обратите внимание, что в документах предлагается использовать отступы, а не поля: android:paddingTop=?android:attr/actionBarSize (developer.android.com/training/basics/actionbar/overlaying.html)   -  person greg7gkb    schedule 26.02.2014


Ответы (5)


И теперь это отлично работает для верхней стороны, но по какой-то причине внизу представления также есть поле, что для меня вообще не имеет никакого смысла. Вот скриншот.

Если вы установите гравитацию ListView на start|bottom, это решит вашу проблему. Никаких дополнительных полей внизу не добавляется. Похоже, гравитация DrawerLayout по умолчанию — start|center

<ListView
    android:id="@+id/left_drawer"
    android:layout_marginTop="?android:attr/actionBarSize"
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:layout_gravity="start|bottom"/>
person kofi    schedule 10.06.2013

В случае, если кто-то заинтересован в другом ответе на этот вопрос. Вот что произошло.

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

android:layout_marginTop="?android:attr/actionBarSize"

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

Итак, я внимательно посмотрел на приложение Play Music и заметил, что на самом деле это не поле, а скорее какое-то дополнение, и, кроме того, они используют собственный фон, который заполняет пространство, указанное дополнением, прозрачным цветом.

Вот что я сделал:

  • Установите Padding в верхней части ListView, а не в поле:

    android:paddingTop="?android:attr/actionBarSize"

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

  • Создайте пользовательский рисунок с прозрачной верхней частью, а затем сплошным цветом:

Выглядит это как-то так:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
    <shape  android:shape="rectangle">
        <solid android:color="#80000000" />
    </shape>
</item>

<item android:top="@dimen/action_bar_default_height">
    <shape
            android:shape="rectangle">
        <solid android:color="@color/light_gray" />
    </shape>
</item>

Note that I tried to use ?android:attr/actionBarSize on the drawable, but that made the app force close. Instead, I searched through grepcode and found a few dimen files with different sizes for the action bar, so I added those to my own project's dimen files.

  • Для значений: 48 дп
  • Для ценностей-земли: 40dp
  • Для значений-sw600dp: 56dp

И после этого я думаю, что выгляжу отлично, обратите внимание на скриншот, как список и панель действий не перекрываются, а прозрачная часть списка имеет правильный размер.

введите здесь описание изображения

Надеюсь, это поможет любому, кто задавался вопросом, как этого добиться.

person daniel_c05    schedule 31.05.2013
comment
Я попробовал ваше решение, но не смог заставить его работать. Установлен ли фон для просмотра списка? - person ebernie; 01.04.2014
comment
Где вы реализовали это? Создайте пользовательский рисунок, верхняя часть которого прозрачна, а остальная часть сплошного цвета? - person Steve Luck; 09.11.2015

Вы можете установить отступ в верхней части макета, чтобы содержимое отображалось под панелью действий.

Просто добавьте это в родительский макет:

android:layout_marginTop="?android:attr/actionBarSize"

Атрибут actionBarSize относится, как вы уже догадались, к размеру ActionBar. Вы не можете установить абсолютное значение в качестве поля, так как ActionBar не всегда имеет одинаковый размер на всех устройствах Android (на планшетах он больше, на мобильных устройствах меньше).

Редактировать:

Установите поле на ListView.

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

    <ListView
        android:id="@+id/left_drawer"
        android:layout_marginTop="?android:attr/actionBarSize"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"/>
</android.support.v4.widget.DrawerLayout>

Приложение Google Music делает то же самое:

введите здесь описание изображения

person Ahmad    schedule 31.05.2013
comment
Не будет ли это также устанавливать поле для макета кадра? и, следовательно, сделать так, чтобы содержимое фрагмента отображалось под панелью действий? - person daniel_c05; 31.05.2013
comment
Да, это поместит все ниже ActionBar - person Ahmad; 31.05.2013
comment
Точно, и это создаст проблему, поскольку я ожидаю, что содержимое будет использовать прозрачность панели действий, поэтому я использую наложение для начала. Я только хочу, чтобы ящик был ниже панели действий. - person daniel_c05; 31.05.2013
comment
Эй, Ахмад, не могли бы вы взглянуть на отредактированный вопрос? Спасибо! - person daniel_c05; 31.05.2013
comment
@daniel_c05 извините, был офлайн. Но похоже, что вы уже решили проблему. - person Ahmad; 31.05.2013

Я решил эту проблему с помощью paddingTop:

<FrameLayout
    android:id="@+id/menu_frame"
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:paddingTop="?attr/actionBarSize" >

    <ListView 
        android:id="@+id/left_drawer_list"
        android:layout_width="240dp"
        android:layout_height="match_parent" />

</FrameLayout>

надеюсь, это поможет

person Vadim Bryl    schedule 04.01.2014

Я создал рабочую демонстрацию, следуя приведенному выше руководству, и протестировал ее на версиях от 2.x до 5.x.

Вы можете клонировать с Github.

Важная вещь, с которой нужно поиграть, находится в основной деятельности.

    toolbar = (Toolbar) findViewById(R.id.toolbar);
    res = this.getResources();

    this.setSupportActionBar(toolbar);
    ActionBar actionBar = getSupportActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
    actionBar.setHomeButtonEnabled(true);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
    { 
        ScrimInsetsFrameLayout scrimInsetsFrameLayout = (ScrimInsetsFrameLayout)
                findViewById(R.id.linearLayout);
        scrimInsetsFrameLayout.setOnInsetsCallback(this);
    } 

и обратный звонок

@Override
public void onInsetsChanged(Rect insets) {
      Toolbar toolbar = this.toolbar;
        ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams)
                toolbar.getLayoutParams();
        lp.topMargin = insets.top;
        int top = insets.top;
        insets.top += toolbar.getHeight();
        toolbar.setLayoutParams(lp);
        insets.top = top; // revert
}

Абсолютно тема для V21 творит чудеса

 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

    <!-- API 21 theme customizations can go here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/accent_material_light</item>
    <item name="windowActionModeOverlay">true</item>
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="android:windowTranslucentStatus">true</item>
</style>
person Vipin Sahu    schedule 30.12.2014