MotionLayout-OnSwipe在可点击的子代上不起作用

问题描述

我在使用MotionLayout时遇到问题,如果用户在可点击项目上开始滑动,则无法向上/向下滑动。我希望用户能够在屏幕的任何部分上滑动,并触发滑动转换。

基本上,该行为与Android上的Yelp应用程序上的行为非常相似。在屏幕上的任意位置滑动即可将搜索栏移到屏幕顶部。参见此video的滑动行为。

我的过渡代码如下:

<Transition
    app:constraintSetStart="@id/start"
    app:constraintSetEnd="@id/end"
    >
    <OnSwipe
        app:dragDirection="dragUp"
        app:onTouchUp="decelerate"
        />
</Transition>

我的MotionLayout代码看起来像这样:

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

     <!-- other views -->

     <LinearLayout
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        >

        <TextView
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@string/title"
           android:textColor="@color/black"
           android:textSize="14sp"
           android:linespacingExtra="7sp"
           android:fontFamily="@font/avenir"
           android:layout_marginBottom="16dp"
           />

       <GridView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:numColumns="2"
            android:verticalSpacing="8dp"
            android:horizontalSpacing="12dp"
            android:stretchMode="columnWidth"
            tools:listitem="@layout/griditem" <!-- This layout file contains a single <Button/> -->
            />
    </LinearLayout>
</androidx.constraintlayout.motion.widget.MotionLayout>

这是我尝试过的所有无法完成的事情:

  1. 在可点击视图的onInterceptTouchEvent父级中覆盖ViewGroup(仅在此处返回true会导致我想要的滑动行为,但随后应单击的子视图不再可用。)
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
    if (ev?.action == MotionEvent.ACTION_DOWN) {
        onTouchEvent(ev)
        return false
    }
    return true
}
  1. 在可点击的子视图中覆盖onTouchEvent
override fun onTouchEvent(event: MotionEvent?): Boolean {
    if (event?.action == MotionEvent.ACTION_DOWN) {
        super.onTouchEvent(event)
        return false
    }
    return super.onTouchEvent(event)
}
  1. onInterceptTouchEvent中覆盖MotionLayout
override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
    if (event?.action == MotionEvent.ACTION_MOVE) {
        return super.onInterceptTouchEvent(event)
    }
    return false
}

我看了所有这些StackOverflow帖子(还有更多,但最相关):

关于我在这里可以滑动和单击项目的任何想法?

解决方法

我知道了。这里有两点帮助:

  1. 我使用GridLayoutManager将GridView切换到RecyclerView,并将app:touchAnchorId设置为RecyclerView的ID。
  2. 我实际上在MotionScene文件中有两个过渡,而另一个过渡(不是OnSwipe)是第一个。 MotionScene文件中的顺序很重要。我切换了两个过渡的顺序,然后就可以使用它了。但是,一旦触发了另一个过渡,它将停止工作,因此我不得不在适当的时候使用setTransition将过渡重置回OnSwipe过渡。

希望对遇到此问题的人有所帮助。