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

Motion Layout为不同视图设置独立moveWhenScrollAtTop属性实现滚动联动问题

MotionLayout 双区域滚动效果实现方案

参考布局效果:
布局方案

你当前代码不生效的核心原因是 MotionLayout 默认同一时间仅会激活一个Transition,你定义的两个独立Transition不会自动按顺序串联触发,无法实现先收起Header、再操作Filters的联动效果。


修改思路

  1. 合并为单Transition,通过关键帧拆分两个组件的动画触发区间:
    • 0% ~ 50% 进度段:仅执行Header的收起/展开动画,Filters保持原位
    • 50% ~ 100% 进度段:Header保持收起状态,执行Filters的收起/展开动画
  2. 统一配置OnSwipe属性,同时适配顶部滚动判断和方向逻辑
  3. 增加RecyclerView滚动监听,满足Filters和滑动方向绑定的需求

调整后的MotionScene代码

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:motion="http://schemas.android.com/apk/res-auto">

    <Transition
        android:id="@+id/main_transition"
        app:constraintSetStart="@+id/state_idle"
        app:constraintSetEnd="@+id/state_all_hidden">
        
        <OnSwipe
            motion:dragDirection="dragUp"
            motion:moveWhenScrollAtTop="true"
            motion:touchAnchorId="@id/mainRv"
            motion:touchAnchorSide="top" />

        <!-- 关键帧配置:拆分两个组件的动画区间 -->
        <KeyFrameSet>
            <!-- Header 仅在0-50%进度完成收起 -->
            <KeyPosition
                motion:keyPositionType="parentRelative"
                motion:percentY="0"
                motion:framePosition="50"
                motion:target="@id/headerRv" />
            <KeyAttribute
                android:alpha="0"
                motion:framePosition="50"
                motion:target="@id/headerRv" />

            <!-- Filters 在0-50%进度保持原位,50%-100%完成收起 -->
            <KeyPosition
                motion:keyPositionType="parentRelative"
                motion:percentY="0"
                motion:framePosition="50"
                motion:target="@id/filtersRv" />
            <KeyAttribute
                android:alpha="1"
                motion:framePosition="50"
                motion:target="@id/filtersRv" />
        </KeyFrameSet>
    </Transition>

    <ConstraintSet android:id="@+id/state_idle">
        <Constraint
            android:id="@+id/headerRv"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:alpha="1"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Constraint
            android:id="@+id/filtersRv"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:paddingHorizontal="12dp"
            android:paddingVertical="16dp"
            android:alpha="1"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/headerRv" />

        <ConstraintOverride
            android:id="@id/mainRv"
            motion:visibilityMode="ignore" />
    </ConstraintSet>

    <ConstraintSet android:id="@+id/state_all_hidden">
        <Constraint
            android:id="@+id/headerRv"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:alpha="0"
            app:layout_constraintBottom_toTopOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />

        <Constraint
            android:id="@+id/filtersRv"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:paddingHorizontal="12dp"
            android:paddingVertical="16dp"
            android:alpha="0"
            app:layout_constraintBottom_toTopOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />

        <ConstraintOverride
            android:id="@id/mainRv"
            motion:visibilityMode="ignore" />
    </ConstraintSet>
</MotionScene>

补充业务逻辑适配

在页面代码中添加RecyclerView滚动监听,实现「顶部显示Header、上滑显示Filters、下滑隐藏Filters」的需求:

var isScrollingUp = false
mainRv.addOnScrollListener(object : RecyclerView.OnScrollListener() {
    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        super.onScrolled(recyclerView, dx, dy)
        isScrollingUp = dy > 0
        // 列表滚动到顶部时自动显示Header
        if (!mainRv.canScrollVertically(-1)) {
            motionLayout.setProgress(0f)
            return
        }
        // 上滑时最大进度限制为0.5:仅隐藏Header,保持Filters显示
        // 下滑时允许进度到1.0:Filters同步隐藏
        val maxProgress = if (isScrollingUp) 0.5f else 1.0f
        if (motionLayout.progress > maxProgress) {
            motionLayout.setProgress(maxProgress)
        }
    }
})

内容的提问来源于stack exchange,提问作者Totoro no Totoro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 15:06:05