在 Android 應用開發中,精美的用戶界面可以顯著提升應用品質和用戶體驗。Material Design 組件中的 CollapsingToolbarLayout 能夠為應用添加動態、流暢的折疊效果,讓標題欄不再是靜態的元素。本文將深入探討如何使用 CollapsingToolbarLayout 創建令人驚艷的可折疊標題欄效果。
?一、什么是 CollapsingToolbarLayout?
CollapsingToolbarLayout 是 Android Material Design 庫中的一個專用布局容器,它擴展了普通 Toolbar 的功能,允許標題欄在用戶滾動內容時產生豐富的折疊動畫效果。這種效果常見于許多現代 Android 應用,如新聞詳情頁、商品展示頁等場景,能夠提供更加沉浸式的用戶體驗。
二、使用步驟
環境配置
在開始之前,請確保你的項目中已添加 Material Design 依賴:
dependencies {implementation 'com.google.android.material:material:1.8.0'// 其他依賴...
}
基礎布局結構
要正確使用 CollapsingToolbarLayout,必須遵循特定的布局層級結構:
<androidx.coordinatorlayout.widget.CoordinatorLayoutxmlns: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/main"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"><com.google.android.material.appbar.AppBarLayoutandroid:id="@+id/appBar"android:layout_width="match_parent"android:layout_height="250dp"android:fitsSystemWindows="true"><com.google.android.material.appbar.CollapsingToolbarLayoutandroid:id="@+id/collapsing_toolbar"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"app:contentScrim="?attr/colorPrimary"app:expandedTitleMarginStart="64dp"app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"><!-- 這里放置標題欄內容 --></com.google.android.material.appbar.CollapsingToolbarLayout></com.google.android.material.appbar.AppBarLayout><!-- 可滾動內容區域 --><androidx.core.widget.NestedScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior"><!-- 你的滾動內容 --></androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
層級關系說明:
- CoordinatorLayout 是根容器,負責協調子視圖的交互行為
- AppBarLayout 必須是 CoordinatorLayout 的直接子布局
- CollapsingToolbarLayout 必須作為 AppBarLayout 的直接子布局
- 可滾動內容(如 NestedScrollView、RecyclerView)需要設置 app:layout_behavior="@string/appbar_scrolling_view_behavior"
關鍵屬性詳解
layout_scrollFlags
控制 CollapsingToolbarLayout 的滾動行為,常用值組合:
- scroll:允許布局隨滾動事件滾動(必須包含)
- exitUntilCollapsed:布局折疊完成后保留在界面上,不再移出屏幕
- enterAlways:任何向下滾動操作都會使布局展開
- enterAlwaysCollapsed:類似 enterAlways,但布局以折疊狀態開始展開
- snap:滾動結束時,布局會自動折疊或展開到最接近的狀態
示例:app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
contentScrim
指定 CollapsingToolbarLayout 在折疊狀態及折疊后的背景色,通常設置為應用的主題色:
app:contentScrim="?attr/colorPrimary"
標題相關屬性
- app:title:設置標題文本
- app:expandedTitleTextAppearance:展開狀態下的標題文字樣式
- app:collapsedTitleTextAppearance:折疊狀態下的標題文字樣式
- app:expandedTitleMargin:展開狀態下標題的邊距
定義標題欄內容
在 CollapsingToolbarLayout 中,我們可以添加多種視圖組件來創建豐富的視覺效果:
<com.google.android.material.appbar.CollapsingToolbarLayout...><!-- 背景圖片 --><ImageViewandroid:id="@+id/backdrop"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="centerCrop"android:src="@drawable/header_image"android:contentDescription="@string/header_image_desc"app:layout_collapseMode="parallax"app:layout_collapseParallaxMultiplier="0.7"/><!-- 工具欄 --><androidx.appcompat.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"app:layout_collapseMode="pin"app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/><!-- 其他元素,如浮動按鈕 --><com.google.android.material.floatingactionbutton.FloatingActionButtonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="@dimen/fab_margin"android:src="@drawable/ic_favorite"app:layout_anchor="@id/appBar"app:layout_anchorGravity="bottom|end"app:backgroundTint="?attr/colorPrimary"app:layout_collapseMode="pin"/></com.google.android.material.appbar.CollapsingToolbarLayout>
layout_collapseMode 屬性詳解
- pin:在折疊過程中元素位置始終保持不變,適合用于工具欄和重要操作按鈕
- parallax:元素在折疊過程中會產生視覺差偏移效果,增強視覺層次感
- 對于 parallax 模式,可以使用 layout_collapseParallaxMultiplier?屬性控制視差效果的程度(0.0-1.0)
沉浸式狀態欄實現
為了實現背景圖片延伸到狀態欄的沉浸式效果,需要完成以下步驟:
步驟一:設置 fitsSystemWindows
將需要延伸到狀態欄的控件及其所有父布局的 android:fitsSystemWindows?屬性設為 true
步驟二:設置透明狀態欄主題
在 values/styles.xml 和 values-v21/styles.xml 中定義透明狀態欄主題:
values/styles.xml
<resources><style name="AppTheme" parent="Theme.Material3.DayNight.NoActionBar"><item name="colorPrimary">@color/colorPrimary</item><item name="colorPrimaryDark">@color/colorPrimaryDark</item><item name="colorAccent">@color/colorAccent</item></style>
</resources>
values-v21/styles.xml
<resources><style name="AppTheme" parent="Theme.Material3.DayNight.NoActionBar"><item name="colorPrimary">@color/colorPrimary</item><item name="colorPrimaryDark">@android:color/transparent</item><item name="colorAccent">@color/colorAccent</item><item name="android:statusBarColor">@android:color/transparent</item><item name="android:windowLightStatusBar">true</item></style>
</resources>
三、完整示例代碼
以下是一個完整的可折疊標題欄實現示例:
<androidx.coordinatorlayout.widget.CoordinatorLayoutxmlns: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"android:fitsSystemWindows="true"><com.google.android.material.appbar.AppBarLayoutandroid:id="@+id/app_bar"android:layout_width="match_parent"android:layout_height="@dimen/appbar_height"android:fitsSystemWindows="true"><com.google.android.material.appbar.CollapsingToolbarLayoutandroid:id="@+id/collapsing_toolbar"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"app:contentScrim="?attr/colorPrimary"app:expandedTitleMarginEnd="64dp"app:expandedTitleMarginStart="48dp"app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"app:statusBarScrim="@android:color/transparent"><ImageViewandroid:id="@+id/backdrop"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="centerCrop"app:layout_collapseMode="parallax"app:layout_collapseParallaxMultiplier="0.7" /><androidx.appcompat.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"app:layout_collapseMode="pin"app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /></com.google.android.material.appbar.CollapsingToolbarLayout></com.google.android.material.appbar.AppBarLayout><androidx.core.widget.NestedScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"app:layout_behavior="@string/appbar_scrolling_view_behavior"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="16dp"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="@string/lorem_ipsum"android:textSize="16sp" /></LinearLayout></androidx.core.widget.NestedScrollView><com.google.android.material.floatingactionbutton.FloatingActionButtonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="16dp"android:src="@drawable/ic_share"app:layout_anchor="@id/app_bar"app:layout_anchorGravity="bottom|end" /></androidx.coordinatorlayout.widget.CoordinatorLayout>