如何设置CollapsingToolbarLayout使其不完全隐藏并让视图停在固定位置?
解决CollapsingToolbar不完全隐藏,指定视图到阈值停止移动的方案
嘿,这个需求我之前帮不少开发者搞定过,核心思路要么是精准控制单个视图的滚动行为,要么是调整整个Toolbar的折叠范围。下面给你两种实用的实现方式:
方法一:自定义Behavior,控制指定视图到阈值停止移动
如果只是希望某一个视图(比如标题、Logo)在折叠到一定距离后固定不动,而其他元素继续折叠,最灵活的方式是给这个视图自定义一个CoordinatorLayout.Behavior,监听AppBar的滚动状态,达到阈值就停止移动。
代码实现(Kotlin为例)
import android.content.Context import android.util.AttributeSet import android.view.View import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.CoordinatorLayout class StopAtThresholdBehavior(context: Context, attrs: AttributeSet) : CoordinatorLayout.Behavior<View>(context, attrs) { // 定义停止滚动的阈值(这里设置为200dp,可根据需求调整) private val stopThreshold = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 200f, context.resources.displayMetrics ).toInt() override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View): Boolean { // 依赖AppBarLayout的滚动 return dependency is AppBarLayout } override fun onDependentViewChanged(parent: CoordinatorLayout, child: View, dependency: View): Boolean { val appBar = dependency as AppBarLayout // 计算AppBar已滚动的距离 val scrolledDistance = appBar.totalScrollRange + appBar.top // 当滚动距离超过阈值时,固定视图位置;否则正常跟随滚动 child.translationY = if (scrolledDistance >= stopThreshold) { stopThreshold.toFloat() } else { scrolledDistance.toFloat() } return true } }
布局中使用
给需要固定的视图添加app:layout_behavior属性:
<TextView android:id="@+id/fixed_title" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_behavior="com.yourpackage.StopAtThresholdBehavior" />
方法二:调整CollapsingToolbarLayout的折叠范围,整体不完全隐藏
如果希望整个CollapsingToolbar折叠后保留一定高度(不完全隐藏),可以通过设置minHeight或者自定义CollapsingToolbarLayout来实现。
方式1:直接设置minHeight(简单快捷)
在布局中给CollapsingToolbarLayout设置最小高度,折叠到该高度后就会停止:
<com.google.android.material.appbar.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="120dp" <!-- 折叠后保留的高度,按需调整 --> app:layout_scrollFlags="scroll|exitUntilCollapsed"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin"/> <!-- 其他Toolbar内容,比如Banner图 --> </com.google.android.material.appbar.CollapsingToolbarLayout>
方式2:自定义CollapsingToolbarLayout(更灵活)
如果minHeight满足不了需求,比如需要动态调整折叠高度,可以自定义CollapsingToolbarLayout,重写getCollapsedHeight方法:
import android.content.Context; import android.util.AttributeSet; import android.util.TypedValue; import com.google.android.material.appbar.CollapsingToolbarLayout; public class CustomCollapsingToolbar extends CollapsingToolbarLayout { // 默认折叠后保留120dp高度 private int mCollapsedHeightDp = 120; public CustomCollapsingToolbar(Context context) { super(context); init(); } public CustomCollapsingToolbar(Context context, AttributeSet attrs) { super(context, attrs); init(); } public CustomCollapsingToolbar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { // 将dp转换为像素,适配不同屏幕 mCollapsedHeightDp = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, mCollapsedHeightDp, getResources().getDisplayMetrics() ); } // 重写折叠高度 @Override protected int getCollapsedHeight() { return mCollapsedHeightDp; } // 提供动态修改折叠高度的方法 public void setCollapsedHeightDp(int heightDp) { mCollapsedHeightDp = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, heightDp, getResources().getDisplayMetrics() ); requestLayout(); } }
然后在布局中替换为自定义的类:
<com.yourpackage.CustomCollapsingToolbar android:id="@+id/collapsing_toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <!-- 内容同之前 --> </com.yourpackage.CustomCollapsingToolbar>
注意事项
- 确保
AppBarLayout和CollapsingToolbarLayout的scrollFlags设置正确,scroll|exitUntilCollapsed是实现折叠的基础; - 阈值和折叠高度建议用dp单位转换为像素,避免屏幕适配问题;
- 如果同时使用多个自定义Behavior,要注意视图之间的依赖顺序。
内容的提问来源于stack exchange,提问作者Betojsc
相关产品推荐
相关产品推荐

