Повышение координатораLayout и AppBarLayout

Я создал такой макет AppBar

<android.support.design.widget.AppBarLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/appbar_layout"
    android:layout_height="@dimen/app_bar_height"
    android:layout_width="match_parent"
    android:fitsSystemWindows="true"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    app:elevation="20dp">

    <android.support.design.widget.CollapsingToolbarLayout...>
</android.support.design.widget.AppBarLayout>

он работает и отбрасывает тень в LinearLayout:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include layout="@layout/app_bar_large" />
</LinearLayout>

Однако, когда я помещаю его в тень CoordinatorLayout, она исчезает:

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include layout="@layout/app_bar_large" />
</android.support.design.widget.CoordinatorLayout>

Как я могу заставить панель приложений снова показывать свою тень?

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


person Kata Lune    schedule 07.12.2015    source источник


Ответы (4)


На самом деле это деталь реализации CollapsingToolbarLayout, как показано в исходный код:

if (Math.abs(verticalOffset) == scrollRange) {
  // If we have some pinned children, and we're offset to only show those views,
  // we want to be elevate
  ViewCompat.setElevation(layout, layout.getTargetElevation());
} else {
  // Otherwise, we're inline with the content
  ViewCompat.setElevation(layout, 0f);
}

Что удаляет высоту, когда CollapsingToolbarLayout показывает незакрепленные элементы — по умолчанию она будет иметь высоту только тогда, когда видны только закрепленные дочерние элементы.

person ianhanniballake    schedule 07.12.2015
comment
Интересно, почему этот ответ получил много голосов. Что делать, если у автора нет закрепленных элементов? - person Leo Droidcoder; 07.12.2019
comment
@LeoDroidcoder - в подавляющем большинстве случаев использования CollapsingToolbarLayout внутри него закреплено Toolbar, отсюда и название. Вы, вероятно, вообще не хотите или не должны использовать CollapsingToolbarLayout, если это не так. - person ianhanniballake; 07.12.2019
comment
Там может быть закрепленный Toolbar, который позволит рисовать тень в свернутом состоянии CollapsingToolbarLayout. Но чего хотят многие разработчики, так это рисовать тень и в расширенном состоянии, то есть с любым значением verticalOffset. Хотя это может противоречить рекомендациям по дизайну материалов. - person Leo Droidcoder; 11.12.2019

причина указана выше, попробуйте это решить:

appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
        @Override
        public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
            //some other code here
            ViewCompat.setElevation(appBarLayout, The Elevation In Px);
        }
    });
person halfCup    schedule 05.07.2017
comment
Работает непоследовательно на Android 10 с последней версией AndroidX lib: иногда высота — это та, которую вы просили, иногда она по умолчанию (при прокрутке в NestedView), а иногда она просто исчезла (когда CollapsingToolbarLayout находится в расширенном состоянии). - person flawyte; 16.03.2020

Решение состоит в том, чтобы использовать app:elevation=0dp для удаления высоты по умолчанию и установить android:translationZ на желаемую высоту.

Примечание. В приведенном ниже коде используются последние библиотеки AndroidX/Material, и он может не работать, если вы используете старую библиотеку поддержки.

<com.google.android.material.appbar.AppBarLayout
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:translationZ="8dp"
    app:elevation="0dp">

    <!--
      * `app:elevation=0dp` disables the default shadow that is automatically added on
      scroll ; other values e.g. `6dp` are ignored despite what the official doc says
      (see below)
      * so instead we're using `android:translationZ` to add a shadow with a custom
      elevation
    -->

Документация для AppBarLayout # setTargetElevation() заявляет, что вы можете установить пользовательское значение высоты с помощью атрибута app:elevation, но у меня это не сработало для значений больше 0dp, поэтому я использую translationZ в качестве обходного пути.

person flawyte    schedule 16.03.2020

setTargetElevation() теперь устарело для AppBarLayout.

Новая правильная реализация для применения пользовательского повышения к AppBarLayout на основе состояния макета — использовать StateListAnimator. material-components использует это, как вы можете видеть здесь

Я добавил пример реализации постоянного отображения высоты AppBarLayout здесь, в этой сущности.

Все, что вам нужно, это 1. создать собственный аниматор списка состояний под /res/animator и 2. установить StateListAnimator AppBarLayout следующим образом:

appBarLayout.stateListAnimator = AnimatorInflater.loadStateListAnimator(context, R.animator.appbar_always_elevated_state_list_animator)
person w3bshark    schedule 01.06.2020