Android滚动折叠指定视图:无ActionBar场景下仅折叠ChipGroup的动画实现方案咨询
当然可以实现!完全不需要依赖ActionBar,我给你一套亲测可行的实现思路和代码示例,一步步来:
实现步骤
1. 搭建正确的布局结构
首先得用CoordinatorLayout作为根布局——它是Android实现滚动联动动画的核心容器。我们要把搜索栏固定在顶部,ChipGroup作为可折叠视图,下方放置可滚动的内容(比如RecyclerView):
<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.textfield.TextInputLayout android:id="@+id/search_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp"> <com.google.android.material.textfield.TextInputEditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="搜索内容..." /> </com.google.android.material.textfield.TextInputLayout> <!-- 可折叠的ChipGroup,绑定自定义Behavior --> <com.google.android.material.chip.ChipGroup android:id="@+id/chip_group" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:paddingHorizontal="8dp" app:layout_behavior=".ChipGroupCollapseBehavior"> <com.google.android.material.chip.Chip android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="筛选标签1" /> <com.google.android.material.chip.Chip android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="筛选标签2" /> <!-- 更多筛选标签 --> </com.google.android.material.chip.ChipGroup> <!-- 可滚动内容,绑定系统滚动Behavior --> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
2. 自定义ChipGroup的Behavior
CoordinatorLayout的Behavior可以让我们监听滚动事件,进而控制ChipGroup的折叠/展开动画。创建一个自定义Behavior类:
class ChipGroupCollapseBehavior(context: Context, attrs: AttributeSet) : CoordinatorLayout.Behavior<ChipGroup>(context, attrs) { private var chipGroupTotalHeight = 0 override fun onLayoutChild(parent: CoordinatorLayout, child: ChipGroup, layoutDirection: Int): Boolean { // 记录ChipGroup的初始高度,用于控制折叠范围 chipGroupTotalHeight = child.measuredHeight return super.onLayoutChild(parent, child, layoutDirection) } override fun onStartNestedScroll( coordinatorLayout: CoordinatorLayout, child: ChipGroup, directTargetChild: View, target: View, axes: Int, type: Int ): Boolean { // 只监听垂直方向的滚动事件 return axes == ViewCompat.SCROLL_AXIS_VERTICAL } override fun onNestedScroll( coordinatorLayout: CoordinatorLayout, child: ChipGroup, target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, type: Int, consumed: IntArray ) { super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type, consumed) // 计算新的平移距离:向上滚动(dyConsumed为正)时,ChipGroup向上平移;向下滚动则反向 val currentTranslation = child.translationY val newTranslation = currentTranslation + dyConsumed // 限制平移范围:不能超过ChipGroup的高度(完全折叠),也不能小于0(完全展开) val clampedTranslation = newTranslation.coerceIn(-chipGroupTotalHeight.toFloat(), 0f) // 应用平移动画(硬件加速,性能流畅) child.translationY = clampedTranslation } }
3. 优化动画流畅度
如果觉得直接平移的过渡不够自然,可以添加插值器让动画更丝滑。修改onNestedScroll里的平移代码:
// 替换原来的child.translationY = clampedTranslation child.animate() .translationY(clampedTranslation) .setInterpolator(DecelerateInterpolator()) .setDuration(80) .start()
注意:因为onNestedScroll会被频繁调用,建议只在平移距离变化明显时启动动画,或者直接使用translationY的即时更新(本身已经是硬件加速,性能足够)。
4. 额外注意事项
- 如果你的可滚动内容是
ScrollView,请换成NestedScrollView,这样CoordinatorLayout才能捕获它的滚动事件。 - 可以添加滚动阈值,比如当滚动距离超过50px才开始折叠,避免轻微滚动就触发动画。
- 测试时注意不同屏幕尺寸下的适配,确保ChipGroup能完全折叠隐藏。
这样设置之后,当你向上滚动页面内容时,ChipGroup会平滑向上折叠隐藏;向下滚动时,又会自动展开回来——完全符合你的需求,而且全程不需要依赖ActionBar。
内容的提问来源于stack exchange,提问作者BlazeCodeDev
相关产品推荐
相关产品推荐

