Подтвердить что ты не робот

Android Navigation Drawer и windowActionBarOverlay = true

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

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

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

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

enter image description here

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

enter image description here

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

РЕДАКТИРОВАТЬ Итак, согласно помощи Ахмада, я устанавливаю 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"
          />

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

Не уверен, что это заставляет: (

4b9b3361

Ответ 1

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

Я попытался установить только край в верхней части списка, например:

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

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

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

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

  • Устанавливаем заполнение в верхней части списка 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>

Обратите внимание, что я попытался использовать ?android:attr/actionBarSize в drawable, но это заставило силу приложения закрыть. Вместо этого я просмотрел grepcode и нашел несколько файлов dimen с разными размерами для панели действий, поэтому я добавил их в свои собственные файлы проекта dimen.

  • Для значений: 48dp
  • Для значений-land: 40dp
  • Для значений-sw600dp: 56dp

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

enter image description here

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

Ответ 2

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

Если вы установите гравитацию ListView на start | bottom, она решит вашу проблему. Никакой дополнительный запас не добавляется внизу. Похоже, что сила DrawerLayout по умолчанию - начало | 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"/>

Ответ 3

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

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

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

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

Edit:

Задайте значение поля 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 делает то же самое:

enter image description here

Ответ 4

Я решил эту проблему, используя 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>

Надеюсь, что поможет

Ответ 5

Я создал рабочую демонстрацию, следуя приведенному выше руководству, и протестировал ее на 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>