如何实现CollapsingToolbarLayout折叠时Toolbar与TabLayout保持可见?
CollapsingToolbarLayout 定制实现方案
需求说明
我有一个带有app:contentScrim动画效果的CollapsingToolbarLayout,内部包含Toolbar、ImageView和TabLayout,需要实现以下效果:
- 滚动时隐藏ImageView,上滑折叠视图时Toolbar和TabLayout保持可见
- 展开CollapsingToolbarLayout时,Toolbar和TabLayout背景为透明;折叠时切换为
app:contentScrim指定的纯色
布局文件实现
<?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"> <com.google.android.material.appbar.AppBarLayout android:id="@+id/app_bar_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true"> <com.google.android.material.appbar.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" app:contentScrim="@color/primary_color" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <!-- 滚动时隐藏的头部图片 --> <ImageView android:id="@+id/header_image" android:layout_width="match_parent" android:layout_height="200dp" android:scaleType="centerCrop" android:src="@drawable/header_bg" app:layout_collapseMode="parallax" /> <!-- 固定在顶部的Toolbar --> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@android:color/transparent" app:layout_collapseMode="pin" /> </com.google.android.material.appbar.CollapsingToolbarLayout> <!-- 固定在AppBar底部的TabLayout,折叠时保持可见 --> <com.google.android.material.tabs.TabLayout android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/transparent" app:tabIndicatorColor="@color/white" app:tabTextColor="@color/white" /> </com.google.android.material.appbar.AppBarLayout> <!-- 滚动内容区域,绑定AppBar的滚动行为 --> <androidx.viewpager2.widget.ViewPager2 android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
滚动监听与动画逻辑实现(Kotlin)
import android.graphics.Color import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.core.graphics.ColorUtils import com.google.android.material.appbar.AppBarLayout class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val appBarLayout = findViewById<AppBarLayout>(R.id.app_bar_layout) val collapsingToolbar = findViewById<com.google.android.material.appbar.CollapsingToolbarLayout>(R.id.collapsing_toolbar) val toolbar = findViewById<androidx.appcompat.widget.Toolbar>(R.id.toolbar) val tabLayout = findViewById<com.google.android.material.tabs.TabLayout>(R.id.tab_layout) val headerImage = findViewById<android.widget.ImageView>(R.id.header_image) // 获取contentScrim设置的纯色值 val scrimColor = collapsingToolbar.contentScrim?.defaultColor ?: Color.parseColor("#2196F3") appBarLayout.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { _, verticalOffset -> // 计算折叠进度:0=完全展开,1=完全折叠 val collapseRatio = Math.abs(verticalOffset).toFloat() / appBarLayout.totalScrollRange.toFloat() // 控制ImageView的显示/隐藏:折叠进度超过0.3时隐藏,否则显示并调整透明度 headerImage.alpha = 1 - collapseRatio * 3.3f headerImage.visibility = if (collapseRatio > 0.3) android.view.View.GONE else android.view.View.VISIBLE // 动态调整Toolbar和TabLayout的背景色透明度,实现从透明到scrimColor的过渡 val alphaValue = (collapseRatio * 255).toInt() val targetColor = ColorUtils.setAlphaComponent(scrimColor, alphaValue) toolbar.setBackgroundColor(targetColor) tabLayout.setBackgroundColor(targetColor) }) } }
关键实现要点
- 布局层级设计:将TabLayout放在
AppBarLayout内部、CollapsingToolbarLayout外部,确保折叠时TabLayout始终固定在顶部;ImageView设置parallax折叠模式实现滚动视差,Toolbar设置pin模式固定不跟随折叠。 - 折叠进度监听:通过
AppBarLayout.OnOffsetChangedListener获取折叠偏移量,计算collapseRatio作为动画进度的依据,统一控制ImageView的显示状态和背景色的透明度变化。 - 动画细节优化:ImageView的隐藏阈值(0.3)可根据需求调整,背景色的透明度直接绑定折叠进度,保证动画平滑无断层。
内容的提问来源于stack exchange,提问作者Moz
相关产品推荐
相关产品推荐

