运动布局:处理可滑动视图上的点击

问题描述 投票:0回答:1

我正在尝试为cardView设置一个触摸监听器(由于运动布局,它也是可滑动的),问题是,如果我在onTouchListener中返回true,当event.action == ACTION_DOWN时(这样我就可以在用户从cardView上抬起手指)该cardView上的滑动动画不起作用。当用户抬起手指时,我需要执行我的逻辑,因为如果我在 ACTION_DOWN 上执行逻辑,那么在用户刷卡视图时,我的逻辑也会被执行(我希望仅当用户点击时才执行逻辑)在卡片上查看)。
这是 xml 布局:

<androidx.constraintlayout.motion.widget.MotionLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
app:motionDebug="SHOW_ALL"
android:id="@+id/matchingMotionLayout"
android:layout_width="match_parent"
app:layoutDescription="@xml/matching_scene"
android:layout_height="match_parent">

<com.google.android.material.card.MaterialCardView
    android:id="@+id/cardTwo"
    android:layout_width="320dp"
    android:layout_height="480dp"
    app:cardBackgroundColor="@color/design_default_color_secondary"
    app:cardCornerRadius="24dp"
    app:layout_constraintBottom_toTopOf="@id/dislikeButton"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/matchingWithTitle"
    app:layout_constraintVertical_bias="0.4">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ImageView
            android:id="@+id/bottomImage"
            android:layout_height="0dp"
            android:layout_width="match_parent"
            android:scaleType="centerCrop"
            app:layout_constraintBottom_toTopOf="@id/bottomInterestPointName"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/bottomInterestPointName"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:elevation="1dp"
            android:gravity="center_horizontal"
            android:paddingVertical="24dp"
            android:textColor="@android:color/white"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            tools:text="Restaurant Name" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</com.google.android.material.card.MaterialCardView>

<com.google.android.material.card.MaterialCardView
    android:id="@+id/cardOne"
    android:layout_width="320dp"
    android:layout_height="480dp"
    app:layout_constraintBottom_toTopOf="@id/dislikeButton"
    app:cardBackgroundColor="@color/md_theme_light_primary"
    app:cardCornerRadius="24dp"
    app:layout_constraintTop_toBottomOf="@id/matchingWithTitle"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintVertical_bias="0.4">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/cardOneLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ImageView
            android:id="@+id/topImage"
            android:layout_height="0dp"
            android:scaleType="centerCrop"
            android:layout_width="match_parent"
            app:layout_constraintBottom_toTopOf="@id/topInterestPointName"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/topInterestPointName"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:elevation="1dp"
            android:gravity="center_horizontal"
            android:paddingVertical="24dp"
            android:textColor="@android:color/white"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            tools:text="Restaurant Name" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</com.jhn.restaurantpicker.ui.core.TestCardView>

...

</com.jhn.restaurantpicker.ui.core.TestMotionLayout>

这是我的运动场景转换:

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

<Transition
    android:id="@+id/startToLeft3"
    app:constraintSetEnd="@+id/unlike"
    app:constraintSetStart="@+id/start">

    <OnSwipe
        app:dragDirection="dragLeft"
        app:touchAnchorId="@id/cardOne"
        app:touchAnchorSide="left"
        app:touchRegionId="@id/cardOne" />

    <KeyFrameSet>

        <KeyPosition
            app:framePosition="50"
            app:keyPositionType="pathRelative"
            app:motionTarget="@id/cardOne"
            app:percentY="0.3" />

        <KeyPosition
            app:framePosition="50"
            app:keyPositionType="pathRelative"
            app:motionTarget="@id/topInterestPointName"
            app:percentY="0.3" />

    </KeyFrameSet>

</Transition>

<Transition
    android:id="@+id/startToRight3"
    app:constraintSetEnd="@+id/like"
    app:constraintSetStart="@+id/start">

    <OnSwipe
        app:dragDirection="dragRight"
        app:touchAnchorId="@id/cardOne"
        app:touchAnchorSide="right"
        app:touchRegionId="@id/cardOne" />

    <KeyFrameSet>

        <KeyPosition
            app:framePosition="50"
            app:keyPositionType="pathRelative"
            app:motionTarget="@id/cardOne"
            app:percentY="-0.3" />

        <KeyPosition
            app:framePosition="50"
            app:keyPositionType="pathRelative"
            app:motionTarget="@id/topInterestPointName"
            app:percentY="-0.3" />

    </KeyFrameSet>

</Transition>
...
这是片段中的转换侦听器:
matchingMotionLayout.setTransitionListener(object : TransitionAdapter() {
            override fun onTransitionCompleted(motionLayout: MotionLayout, currentId: Int) {
                when (currentId) {
                    R.id.offScreenUnlike -> {
                        if (vm.shouldResetScene) {
                            motionLayout.progress = 0f
                            motionLayout.setTransition(R.id.start, R.id.start)
                        }
                        vm.unlike()
                    }

                    R.id.offScreenLike -> {
                        if (vm.shouldResetScene) {
                            motionLayout.progress = 0f
                            motionLayout.setTransition(R.id.start, R.id.start)
                        }
                        vm.like()
                    }

                    R.id.start -> {
                        motionLayout.progress = 0f
                        motionLayout.setTransition(R.id.start, R.id.start)
                    }
                }
                super.onTransitionCompleted(motionLayout, currentId)
            }
        })
android xml kotlin touch-event android-motionlayout
1个回答
0
投票

对我有用的解决方案: 因此,在连续 1 周尝试不同的方法后,我终于找到了有效的方法。

  1. 我创建了一个自定义 MotionLayout 类,在其中重写 onInterceptTouchEvent()。在此方法中,仅当操作等于 ACTION_MOVE 时,我才返回 true。
class ClickableMotionLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : MotionLayout(context, attrs, defStyleAttr) {

    override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
        return event?.action == MotionEvent.ACTION_MOVE
    }
}
  1. 在片段中,我在我们(滑动/单击)的视图上设置了一个 touchListener:
    cardOne.setOnTouchListener(imageSeekListener)

在 touchListener 中,我通过传递 touchListener 接收到的事件来调用 MotionLayout 的 onTouchEvent,当操作为 ACTION_DOWN 时,我返回 true。

    private var imageSeekListener: View.OnTouchListener? = View.OnTouchListener { v, event ->
    binding.matchingMotionLayout.onTouchEvent(event)
    if (event.action == MotionEvent.ACTION_DOWN) {
        return@OnTouchListener true
    }
    if (event.action == MotionEvent.ACTION_UP) {
        when (getTouchSide(v, event)) {
            TouchSide.LEFT -> vm.peekPreviousPhoto()
            TouchSide.RIGHT -> vm.peekNextPhoto()
        }
    }
    return@OnTouchListener false
    }

现在我可以点击卡片来查看照片,然后滑动卡片以显示另一张卡片,而无需触发点击。希望它对某人有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.