Координатор использует специальные классы behavior, в которых описывается поведение View, он может наблюдать за изменениями состояния одного View и, соответственно, изменять состояние другого View. В общем, этот инструмент создан специально для реализации таких вот шапок.
<androidx.coordinatorlayout.widget.CoordinatorLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><include layout="@layout/main_app_bar" /> <!-- шапки --><!-- остальной контент, у которого выставляемapp:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"--></androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.appbar.AppBarLayoutxmlns: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="wrap_content"><com.google.android.material.appbar.CollapsingToolbarLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"app:layout_scrollFlags="scroll|snap|exitUntilCollapsed"><include layout="@layout/short_main_promo_header"/><include layout="@layout/main_promo_header" /></com.google.android.material.appbar.CollapsingToolbarLayout></com.google.android.material.appbar.AppBarLayout>
override fun onLayoutChild(parent: CoordinatorLayout,abl: AppBarLayout,layoutDirection: Int): Boolean {val superLayout = super.onLayoutChild(parent, abl, layoutDirection)if (collapsingLayout == null) initialize(abl)return superLayout}private fun initialize(abl: AppBarLayout) {collapsingLayout = abl.getChildAt(0) as CollapsingToolbarLayoutpromoHeaderBackground = abl.findViewById(R.id.short_main_promo_header_background)promoHeaderBottom = abl.findViewById(R.id.short_main_promo_header_bottom)appBar = abl}
private var isBlockScroll = falsefun changeScrollBlocking(isBlock: Boolean) {isBlockScroll = isBlock}override fun onNestedScroll(coordinatorLayout: CoordinatorLayout,child: AppBarLayout,target: View,dxConsumed: Int,dyConsumed: Int,dxUnconsumed: Int,dyUnconsumed: Int,type: Int,consumed: IntArray) {super.onNestedScroll(coordinatorLayout,child,target,dxConsumed,dyConsumed,dxUnconsumed,if (isBlockScroll) {0} else {dyUnconsumed},type,consumed)}
override fun setTopAndBottomOffset(offset: Int): Boolean {val scrollProgress = MathUtils.clamp(-offset / maximumVerticalOffset, 0f, 1f)appBar?.alpha = 1 - scrollProgresspromoHeaderBackground?.translationY = scrollProgresspromoHeaderBottom?.translationY = scrollProgress * 2return super.setTopAndBottomOffset(offset)}
init {collapsingToolbarView.minimumHeight = minHeightcollapsingToolbarView.fitsSystemWindows = trueview.addOnOffsetChangedListener { _, verticalOffset ->val percentage = MathUtils.clamp(abs(verticalOffset / maximumVerticalOffset), 0f, 1f)actionsFlow.tryEmit(BxContentAction.AnimateToolbar(percentage))when (percentage) {0f -> {actionsFlow.tryEmit(BxContentAction.ChangeShortMainPromoHeaderState(false))actionsFlow.tryEmit(BxContentAction.ChangeToolbarBackground(false))}1f -> {actionsFlow.tryEmit(BxContentAction.ChangeShortMainPromoHeaderState(true))actionsFlow.tryEmit(BxContentAction.ChangeToolbarBackground(true))}}}}
(params.behavior as? AppBarLayout.ScrollingViewBehavior)?.overlayTop = 16.dp