You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 12:03:37