Я наконец понял это. Я поделюсь кодом для файла XML в том виде, в котором он есть, а затем объясню все об этом позже.
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="256dp"
android:minHeight="132dp"
android:fitsSystemWindows="true"
app:titleEnabled="false"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<View
android:id="@+id/blue_view"
android:layout_width="match_parent"
android:layout_height="128dp"
android:background="@android:color/holo_blue_bright"
app:layout_collapseMode="pin"
app:layout_collapseParallaxMultiplier="0"
android:layout_gravity="top"/>
<HorizontalScrollView
android:id="@+id/pink_view"
android:layout_width="match_parent"
android:layout_height="128dp"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="1"
android:layout_gravity="bottom">
<View
android:layout_width="2000dp"
android:minWidth="2000dp"
android:layout_height="match_parent"
android:background="@color/colorAccent"/>
</HorizontalScrollView>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Примечание. Я использовал View
с разными цветами, чтобы предварительно просмотреть разные сегменты в макете. Я также использовал HorizontalScrollView
, чтобы продемонстрировать что-то вроде RecyclerView
, как в загруженном вами gif.
Хорошо, поэтому сначала нам нужно создать CollapsingToolbarLayout
с layout_scrollFlags
.
- мы используем флаг
scroll
должен быть включен для всех эффектов прокрутки для вступления в силу - мы используем флаг
snap
, чтобы определить, что делать, когда только вид был частично уменьшен. Если прокрутка заканчивается и размер вида был уменьшен до менее чем 50% от исходного, тогда этот вид возвращается к исходному размеру. Если размер больше 50% от его размера, он полностью исчезнет. - мы используем
exitUntilCollapsed
вместе с minHeight
, чтобы свернуть Toolbar
до указанного minHeight
Мы хотим, чтобы CollapsingToolbarLayout
имел:
layout_height
, установленный на расширенную высоту Toolbar
minHeight
установлен на свернутую высоту Toolbar
В этом случае, так как мы хотим HorizontalScrollView
(pink_view
) только чтобы уменьшить в высоту , мы устанавливаем для minHeight
значение [ высота из blue_view
+ меньшее высота из pink_view
]
Следовательно, поскольку blue_view
останется 128dp
и мы хотим, чтобы pink_view
до go до 4dp
, мы установим minHeight
в 132dp
.
Итак, вот небольшой пример. Предположим, что blue_view
походит на 100dp
, а pink_view
изначально 100dp
. Итак, вот как мы хотим, чтобы это сначала показывалось, , но когда я начинаю прокручивать , мы хотим, чтобы pink_view
до go уменьшилось до 20dp
, а blue_view
останется на 100dp
.
Следовательно, layout_height
будет 200dp
, а minHeight
будет 120dp.
Теперь мы хотим, чтобы HorizontalScrollView
или pink_view
свернуть с CollapsingToolbarLayout
высотой .
Итак, мы добавляем layout_collapseMode="parallax"
к pink_view
так, что он прокручивается вместе с CollapsingToolbarLayout
.
. layout_collapseParallaxMultiplier
определяет, какая часть изображения (в процентах) будет скрыта под нижним содержимым. И здесь мы хотим, чтобы это все было скрыто. Поэтому мы устанавливаем значение 1
.
Тем временем мы хотим, чтобы blue_view
оставался закрепленным наверху. И мы также не хотим, чтобы он был скрыт под каким-либо нижним содержимым.
Итак, мы добавляем layout_collapseMode="pin"
к blue_view
таким образом, что он прикрепляется к вершине CollapsingToolbarLayout
.
Мы также добавляем layout_collapseParallaxMultiplier="0"
, чтобы он не скрывался ни под каким содержимым.
Обратите внимание, что если высота элементов превышает minHeight
, CollapsingToolbarLayout
будет помещен над экраном. Тогда будет казаться, что высота верхнего элемента (здесь blue_view
) уменьшается в размере.
Предварительный просмотр:
Вот еще одна демонстрация с RecyclerView
:
XML для вышеупомянутого RecyclerView
демоверсия ниже, если кому-то интересно * и ViewHolder
, мы должны изменить их размер, когда offset
из AppBarLayout
изменяется при прокрутке.
Это потому, что CollapsingToolbarLayout
просто прокручивает элементы внутри него друг под другом вместо фактического изменения их размера.
Итак, мы должны использовать RecyclerView
, называемый здесь hv_list
, и AppBarLayout
, называемый здесь app_bar
.
val hv_list: RecyclerView = findViewById(R.id.hv_list)
val app_bar: AppBarLayout = findViewById(R.id.app_bar)
После этого нам нужно запомнить исходный размер hv_list
.
val hv_original_height: Int = hv_list.layoutParams.height
Наконец, нам нужно установить OffsetChangedListener
для AppBarLayout
. Там мы изменим высоту RecyclerView
и затем добавим нижнее поле к pu sh до только потому, что оно имеет гравитационное дно .
app_bar.addOnOffsetChangedListener(object : AppBarLayout.OnOffsetChangedListener {
override fun onOffsetChanged(appBarLayout: AppBarLayout, i: Int) {
hv_list.updateLayoutParams {
this.height = hv_original_height + i
(this as CollapsingToolbarLayout.LayoutParams).setMargins(0, 0, 0, abs(i))
}
}
})
Убедитесь, что ваш itemView в RecyclerView
имеет высоту из match_parent