33

Я ищу, чтобы добавить поддержку прокрутки не более, чем один, прокручиваемый, дочерний вид CoordinatorLayout в сочетании с AppBarLayout и CollapsingToolbarLayout. При прокрутке RecyclerView или AppBarLayout (сокращенный код ниже) панель приложения и его содержимое успешно прокручиваются и сворачиваются. Однако при попытке инициировать событие прокрутки на LinearLayout выше RecyclerView ничего не происходит, потому что LinearLayout не знает, чтобы прокрутить или свернуть вид.Добавление режима просмотра прокрутки приложения на несколько видов в CoordinatorLayout

Цель состоит в том, чтобы иметь LinearLayout выступать в качестве липкого заголовка к RecyclerView и колонтитулу в AppBarLayout и получить такое же поведение скроллинга как RecyclerView, похожего на Spotify's shuffle play/available offline header. На самом деле было бы здорово, если бы appbar_scrolling_view_behaviorlayout_behavior можно было применить к LinearLayout аналогично RecyclerView, но я полагаю, что поведение игнорируется на прокручиваемых представлениях. Кто-нибудь знает об обходном пути для этого, который не требует реализации вида LinearLayout в виде строки в RecyclerView?

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

    <android.support.design.widget.AppBarLayout 
     android:id="@+id/app_bar_layout" 
     android:layout_width="match_parent" 
     android:layout_height="@dimen/collapsible_app_bar_height" 
     android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> 

     <android.support.design.widget.CollapsingToolbarLayout 
      android:id="@+id/collapsing_toolbar_layout" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:background="@drawable/gradient_banner" 
      app:contentScrim="@color/background_content_frame" 
      app:layout_scrollFlags="scroll|exitUntilCollapsed"> 

      <ImageView 
       android:id="@+id/image_header" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       android:src="@drawable/some_image" 
       app:layout_collapseMode="parallax"/> 

      <android.support.v7.widget.Toolbar 
       android:id="@+id/collapsible_toolbar" 
       android:layout_width="match_parent" 
       android:layout_height="?attr/actionBarSize" 
       android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" 
       app:layout_collapseMode="pin"/> 

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

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

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="@dimen/slide_handle_height" 
     android:orientation="horizontal" 
     android:background="@color/slide_handle" 
     android:gravity="center_vertical"> 

     <!-- three buttons --> 

    </LinearLayout> 

    <android.support.v7.widget.RecyclerView 
     android:id="@+id/recycler_view" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:layout_marginTop="@dimen/slide_handle_height" 
     android:scrollbars="vertical" 
     app:layout_behavior="@string/appbar_scrolling_view_behavior"/> 

</android.support.design.widget.CoordinatorLayout> 
+0

Возможно, это невозможно, потому что Spotify не использует библиотеку поддержки дизайна, но я не знаю –

+0

@MarioVelasco Правильно, Spotify не использует реализацию CollapsingToolbarLayout, но я ссылался на нее как пример поведения, м, стремясь достичь через какое-то обходное решение. – Ryan

+0

Хорошие новости! У меня есть реальное решение для вас. Это позволит решить, что вы пытаетесь сделать, взглянуть и пометить как это было принято, если вам это нравится. –

ответ

6

После нескольких проб и ошибок, это сокращенный вариант макет, который в конечном итоге работал для меня:

<android.support.design.widget.CoordinatorLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/coordinator_layout" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

<android.support.design.widget.AppBarLayout 
    android:id="@+id/app_bar_layout" 
    android:layout_width="match_parent" 
    android:layout_height="@dimen/collapsible_app_bar_height" 
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> 

    <android.support.design.widget.CollapsingToolbarLayout 
     android:id="@+id/collapsing_toolbar_layout" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     app:contentScrim="@color/background_content_frame" 
     app:layout_scrollFlags="scroll|exitUntilCollapsed"> 

     <ImageView 
      android:id="@+id/image_header" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:layout_gravity="center_horizontal" 
      android:layout_marginBottom="@dimen/button_bar_height" 
      android:scaleType="centerCrop" 
      android:background="@android:color/transparent" 
      android:src="@drawable/default_header" 
      android:contentDescription="@string/description_content_image" 
      app:layout_collapseMode="parallax"/> 

     <ImageView 
      android:id="@+id/image_header_gradient" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:layout_marginBottom="@dimen/button_bar_height" 
      android:src="@drawable/scrim_top_bottom_banner" 
      app:layout_collapseMode="parallax" 
      tools:ignore="ContentDescription"/> 

     <android.support.v7.widget.Toolbar 
      android:id="@+id/collapsible_toolbar" 
      android:layout_width="match_parent" 
      android:layout_height="104dp" 
      android:minHeight="?attr/actionBarSize" 
      android:gravity="top" 
      android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" 
      app:contentInsetStart="0dp" 
      app:titleMargins="0dp" 
      app:layout_collapseMode="pin"/> 

     <RelativeLayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:layout_marginStart="@dimen/landing_header_button_margin_horizontal" 
      android:layout_marginEnd="@dimen/landing_header_button_margin_horizontal" 
      android:layout_marginBottom="@dimen/button_bar_height" 
      android:layout_gravity="bottom" 
      android:gravity="center_vertical" 
      app:layout_collapseMode="parallax"> 

      <Button 
       android:id="@+id/button_one" 
       android:layout_alignParentStart="true" 
       android:drawableStart="@drawable/selector_one" 
       android:textColor="@color/alabaster_white" 
       android:visibility="gone" 
       style="@style/Button.TextCount"/> 

      <Button 
       android:id="@+id/button_two" 
       android:layout_alignParentEnd="true" 
       android:layout_gravity="end" 
       android:drawableStart="@drawable/selector_two" 
       android:textColor="@color/alabaster_white" 
       android:visibility="gone" 
       style="@style/Button.TextCount"/> 

     </RelativeLayout> 

     <LinearLayout 
      android:layout_width="match_parent" 
      android:layout_height="@dimen/button_bar_height" 
      android:layout_gravity="bottom" 
      android:gravity="center_vertical" 
      android:orientation="horizontal" 
      android:background="@color/slide_handle"> 

      <!-- three buttons --> 

     </LinearLayout> 

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

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

<android.support.v7.widget.RecyclerView 
    android:id="@+id/recycler_view" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:scrollbars="vertical" 
    app:layout_behavior="@string/appbar_scrolling_view_behavior"/> 

+7

эй @ Ryan, можете ли вы приложить скриншот или видео-демо вашего решения? – carlosmaciel

+0

Это не должно быть принятым ответом. Отсутствует скриншот или видео, отображающее макет. Кроме того, существуют стили и размеры, на которые в ответе не ссылаются. –

35

Вам не нужен обходной путь или что-то странное. Такое поведение поддерживается библиотекой. Просто замените ваши LinearLayout этим и поставить его ниже RecyclerView:

<android.support.v4.widget.NestedScrollView 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    app:layout_behavior="@string/appbar_scrolling_view_behavior"> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation="vertical" 
     android:gravity="center"> 

     <Button 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:padding="15dp" 
      android:text="Button text"/> 

    </LinearLayout> 

</android.support.v4.widget.NestedScrollView> 

Также вам нужно будет сделать это в вашем RecyclerView, чтобы показать его за LinearLayout:

android:paddingTop="30dp" 
    android:clipToPadding="false" 

Вот как это будет выглядеть например:

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

<android.support.design.widget.AppBarLayout 
    android:id="@+id/app_bar_layout" 
    android:layout_width="match_parent" 
    android:layout_height="@dimen/collapsible_app_bar_height" 
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> 

    <android.support.design.widget.CollapsingToolbarLayout 
     android:id="@+id/collapsing_toolbar_layout" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:background="@drawable/gradient_banner" 
     app:contentScrim="@color/background_content_frame" 
     app:layout_scrollFlags="scroll|exitUntilCollapsed"> 

     <ImageView 
      android:id="@+id/image_header" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:src="@drawable/some_image" 
      app:layout_collapseMode="parallax"/> 

     <android.support.v7.widget.Toolbar 
      android:id="@+id/collapsible_toolbar" 
      android:layout_width="match_parent" 
      android:layout_height="?attr/actionBarSize" 
      android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" 
      app:layout_collapseMode="pin"/> 

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

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

<android.support.v7.widget.RecyclerView 
    android:id="@+id/recycler_view" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_marginTop="@dimen/slide_handle_height" 
    android:scrollbars="vertical" 
    app:layout_behavior="@string/appbar_scrolling_view_behavior" 
    android:paddingTop="30dp" 
    android:clipToPadding="false"/> 

<android.support.v4.widget.NestedScrollView 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    app:layout_behavior="@string/appbar_scrolling_view_behavior"> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:orientation="vertical" 
     android:gravity="center"> 

     <Button 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:padding="15dp" 
      android:text="Button text"/> 

    </LinearLayout> 

</android.support.v4.widget.NestedScrollView> 

</android.support.design.widget.CoordinatorLayout> 

Это не приятный дизайн, но это решение. Вы можете поместить приятнее Layout внутри LinearLayout, чтобы сделать его похожим на Spotify.

Edit: Видео добавлено

Demo videoDemo video 2

+0

Кажется, что это должно сработать. Тем не менее, я попробовал аналогичный подход некоторое время назад (и только сейчас), а 'NestedScrollView' не реагирует на прокрутку - даже с помощью' appbar_scrolling_view_behavior' 'layout_behavior'. Я считаю, что 'CoordinatorLayout' ищет только один вид для сопоставления с' AppBarLayout' с помощью поведения 'appbar_scrolling_view_behavior'. Поэтому, когда он находит его на «RecyclerView», поиск завершен. В настоящее время я использую способ добавления 'TouchEvent' в' LinearLayout' и перенаправление 'MotionEvent' для запуска прокрутки' RecyclerView' + 'AppBarLayout'. Пока не повезло. – Ryan

+0

Я протестировал с помощью другого 'NestedScrollView' вместо вашего' RecyclerView', и он сработал, я снова проверю с помощью «RecyclerView», и я покажу вам видео. Попробуйте скопировать и вставить xml, который я вам дал, и сообщить мне результаты. –

+0

Кстати, вы видели другой подход, который я написал вам? –

8

Это липкий заголовок положить в середину между Toolbar и RecyclerView:

<Button 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    app:layout_anchor="@+id/app_bar_layout" 
    app:layout_anchorGravity="center|bottom" 
    android:text="Shuffle Play"/> 

Чтобы избежать перекрывающихся с Toolbar вы можете установить разной высоты до AppBarLayout и CollapsingToolbarLayout:

<android.support.design.widget.CoordinatorLayout 
xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
android:id="@+id/main_content" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:fitsSystemWindows="true"> 

<android.support.design.widget.AppBarLayout 
    android:id="@+id/appbar" 
    android:layout_width="match_parent" 
    android:layout_height="240dp" 
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" 
    android:fitsSystemWindows="true"> 

    <android.support.design.widget.CollapsingToolbarLayout 
     android:id="@+id/collapsing_toolbar" 
     android:layout_width="match_parent" 
     android:layout_height="210dip" 
     android:background="?attr/colorPrimary" 
     app:layout_scrollFlags="scroll|exitUntilCollapsed" 
     android:fitsSystemWindows="true" 
     app:contentScrim="?attr/colorPrimary" 
     app:expandedTitleMarginStart="48dp" 
     app:expandedTitleMarginBottom="30dp" 
     app:expandedTitleMarginEnd="64dp"> 

     <ImageView 
      android:id="@+id/backdrop" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:scaleType="centerCrop" 
      android:fitsSystemWindows="true" 
      app:layout_collapseMode="parallax" /> 

     <android.support.v7.widget.Toolbar 
      android:id="@+id/toolbar" 
      android:layout_width="match_parent" 
      android:layout_height="?attr/actionBarSize" 
      app:popupTheme="@style/ThemeOverlay.AppCompat.Light" 
      app:layout_collapseMode="pin" /> 
    </android.support.design.widget.CollapsingToolbarLayout> 

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


<android.support.v7.widget.RecyclerView 
    android:id="@+id/recycler_view" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_marginTop="@dimen/slide_handle_height" 
    android:scrollbars="vertical" 
    app:layout_behavior="@string/appbar_scrolling_view_behavior"/> 

<Button 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    app:layout_anchor="@id/appbar" 
    app:layout_anchorGravity="center|bottom" 
    android:text="Shuffle Play"/> 
</android.support.design.widget.CoordinatorLayout> 

Видео демо:

Demo video

Кроме того, вы можете установить высоту до Toolbar, но нужно будет сделать пользовательский заголовок с помощью пользовательского поведения, как этот proyect CoordinatorLayoutExample.Я сделал это с помощью пользовательского заголовка без поведения:

<android.support.design.widget.CoordinatorLayout 
xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
android:id="@+id/main_content" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:fitsSystemWindows="true"> 

<android.support.design.widget.AppBarLayout 
    android:id="@+id/appbar" 
    android:layout_width="match_parent" 
    android:layout_height="240dp" 
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" 
    android:fitsSystemWindows="true"> 

    <android.support.design.widget.CollapsingToolbarLayout 
     android:id="@+id/collapsing_toolbar" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:background="?attr/colorPrimary" 
     app:layout_scrollFlags="scroll|exitUntilCollapsed" 
     android:fitsSystemWindows="true" 
     app:collapsedTitleTextAppearance="@style/TransparentText" 
     app:expandedTitleTextAppearance="@style/TransparentText" 
     app:contentScrim="?attr/colorPrimary"> 

     <ImageView 
      android:id="@+id/backdrop" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      android:scaleType="centerCrop" 
      android:fitsSystemWindows="true" 
      app:layout_collapseMode="parallax" /> 

     <android.support.v7.widget.Toolbar 
      android:id="@+id/toolbar" 
      android:layout_height="80dp" 
      android:layout_width="match_parent" 
      android:minHeight="?attr/actionBarSize" 
      android:gravity="top" 
      app:popupTheme="@style/ThemeOverlay.AppCompat.Light" 
      app:layout_collapseMode="pin" > 
      <TextView 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content" 
       android:text="Title" 
       android:textSize="20sp" 
       android:textColor="@android:color/white"/> 
     </android.support.v7.widget.Toolbar> 
    </android.support.design.widget.CollapsingToolbarLayout> 

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


<android.support.v7.widget.RecyclerView 
    android:id="@+id/recycler_view" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:layout_marginTop="@dimen/slide_handle_height" 
    android:scrollbars="vertical" 
    app:layout_behavior="@string/appbar_scrolling_view_behavior"/> 

<Button 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    app:layout_anchor="@id/appbar" 
    app:layout_anchorGravity="center|bottom" 
    android:text="Shuffle Play"/> 
</android.support.design.widget.CoordinatorLayout> 

Стили:

<style name="TransparentText" parent="@android:style/TextAppearance"> 
    <item name="android:textColor">#00000000</item> 
</style> 

Видео демо:

enter image description here

+0

@ryan Попробуйте это, чтобы избежать перекрытия –

+0

решение без перекрытия отлично работает, если использовать изображение в AppBarLayout – Alexandr

+0

Я пробовал ваш код макета XML, но в моем случае Shuffle Play Button перекрывается панелью инструментов. так что я должен делать, чтобы этого избежать? –

2

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

layout_anchor="@id/app_bar_layout" 

и

layout_anchorGravity="bottom|right|end" 

в представлении (содержащий ваши кнопки) и поместите его под Toolbar. Также увеличьте высоту над этим видом, потому что когда вы прокрутите вниз, Toolbar будет перекрывать ваше представление.