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

添加setOnClickListener后Motion Layout手动下拉滑动失效求助

问题:MotionLayout视图添加点击事件后滑动功能失效

我是MotionLayout新手,想实现一个类似YouTube视频底部布局的效果:视图可手动下拉至1dp消失,同时点击该视图能跳转至另一个Activity。但给视图添加setOnClickListener后,手动下拉滑动功能就失效了,试了很多教程都没解决。

添加点击事件前的效果:
添加点击事件前的滑动效果

添加点击事件后的效果:
添加点击事件后的滑动失效效果

相关代码片段

主布局(MotionLayout)

<androidx.constraintlayout.motion.widget.MotionLayout
    android:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutDescription="@xml/activity_main_xml_constraintlayout_scene">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:nestedScrollingEnabled="false"
        app:layout_constrainedHeight="true"
        android:scrollbars="vertical"
        app:layout_constraintBottom_toTopOf="@id/motionLayoutExample"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:itemCount="20"
        tools:listitem="@layout/row_rv" />

    <include
        android:id="@+id/motionLayoutExample"
        layout="@layout/view_motion"
        android:layout_width="match_parent"
        android:layout_height="65dp"
        app:layout_constraintBottom_toTopOf="@id/bottomNavView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"/>

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottomNavView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/btn_nav" />

</androidx.constraintlayout.motion.widget.MotionLayout>

注:include标签对应的view_motion布局是需要实现下拉消失和点击跳转的视图区域

Motion Scene配置

<MotionScene 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto">

    <Transition
        android:id="@+id/motionTransitions"
        motion:constraintSetEnd="@+id/end"
        motion:constraintSetStart="@id/start"
        motion:duration="1000">
       <KeyFrameSet>
           <KeyAttribute
               motion:motionTarget="@+id/motionLayoutExample"
               motion:framePosition="100"
               android:alpha="0" />
           <KeyAttribute
               motion:motionTarget="@+id/motionLayoutExample"
               motion:framePosition="75"
               android:alpha="0.5" />
       </KeyFrameSet>
        <OnSwipe
            motion:touchAnchorId="@+id/motionLayoutExample"
            motion:dragDirection="dragDown"
            motion:touchAnchorSide="middle"
            motion:moveWhenScrollAtTop="false"
            motion:nestedScrollFlags="disableScroll"
            motion:onTouchUp="decelerate"
            motion:touchRegionId="@id/motionLayoutExample"/>
    </Transition>

    <ConstraintSet android:id="@+id/start">
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end"
        android:alpha="0">
        <Constraint
            android:id="@+id/motionLayoutExample"
            motion:layout_constraintEnd_toEndOf="parent"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            motion:layout_constraintBottom_toTopOf="@id/bottomNavView"
            motion:layout_constraintTop_toBottomOf="@id/recyclerView"
            motion:layout_constraintStart_toStartOf="parent" />
    </ConstraintSet>
</MotionScene>

导致滑动失效的点击事件代码

motionLayoutExample.setOnClickListener()
{
    Intent(this, SecondActivity::class.java).also()
    {
        startActivity(it)
    }
}

解决方案

方法一:给view_motion内部视图设置点击事件

不要直接给include的根视图(motionLayoutExample)设置点击事件,而是打开view_motion.xml,在其内部的可点击子视图(比如整个布局的容器)上绑定点击事件。这样根视图的触摸事件会优先传递给MotionLayout处理滑动,内部视图单独响应点击。

示例view_motion.xml修改:

<!-- view_motion.xml -->
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="65dp"
    android:background="#FF0000"
    android:orientation="vertical">

    <!-- 内部可点击区域 -->
    <TextView
        android:id="@+id/tv_click_area"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="点击跳转"
        android:gravity="center"/>

</LinearLayout>

对应代码中绑定点击事件:

findViewById<TextView>(R.id.tv_click_area).setOnClickListener {
    startActivity(Intent(this, SecondActivity::class.java))
}

方法二:自定义触摸逻辑区分滑动与点击

如果必须给include的根视图设置点击事件,可以通过自定义OnTouchListener,判断触摸动作是滑动还是点击:

var downX = 0f
var downY = 0f

motionLayoutExample.setOnTouchListener { _, event ->
    when(event.action) {
        MotionEvent.ACTION_DOWN -> {
            downX = event.x
            downY = event.y
            false // 允许MotionLayout处理按下事件
        }
        MotionEvent.ACTION_UP -> {
            val deltaX = abs(event.x - downX)
            val deltaY = abs(event.y - downY)
            // 滑动距离小于阈值则判定为点击
            if (deltaX < 10 && deltaY < 10) {
                startActivity(Intent(this, SecondActivity::class.java))
            }
            false // 让MotionLayout处理后续事件
        }
        else -> false
    }
}

额外优化:调整MotionScene滑动阈值

在MotionScene的OnSwipe标签中添加motion:touchSlop="10dp",增大滑动识别的阈值,避免轻微滑动被误判为点击:

<OnSwipe
    motion:touchAnchorId="@+id/motionLayoutExample"
    motion:dragDirection="dragDown"
    motion:touchAnchorSide="middle"
    motion:moveWhenScrollAtTop="false"
    motion:nestedScrollFlags="disableScroll"
    motion:onTouchUp="decelerate"
    motion:touchRegionId="@id/motionLayoutExample"
    motion:touchSlop="10dp"/>

内容的提问来源于stack exchange,提问作者Pup In The Tree

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 13:09:53