I have a motionlayout with the following 'layoutDescription' (scenes file)
<Transition
motion:constraintSetStart="@+id/start"
motion:constraintSetEnd="@+id/end"
motion:duration="1000">
<OnSwipe
motion:touchAnchorId="@+id/button"
motion:touchAnchorSide="left"
motion:dragDirection="dragLeft" />
</Transition>
<ConstraintSet android:id="@+id/start">
<!-- ConstraintSet for starting -->
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<!-- ConstraintSet for end -->
</ConstraintSet>
What I expect from here is if user drag the 'button' towards left side then it should perform the transition but what actually happening is when user drag left(swipe left) from any where in the screen this transition getting executed!
How to limit the animation work only when dragging the specified view?
(Im using "constraintlayout:2.0.0-beta2" )
Actually for onSwipe
you can use touchRegionId
and targetId
for OnClick
Updated answer : with the ConstraintLayout 2.0.0 alpha-5 you can simply use
app:touchRegionId
in your "OnSwipe" for the same behaviour. Also can use 'app:targetId' for "OnClick" usages.
Thanks @RuslanLeshchenko
Original answer :
I managed to do this finally by extending MotionLayout and override onTouchEvent to forward the event to required view.
Create the custom layout by extending MotionLayout
class SingleViewTouchableMotionLayout(context: Context, attributeSet: AttributeSet? = null) : MotionLayout(context, attributeSet) {
private var viewToDetectTouch1 :View? = null
private var viewToDetectTouchRes :Int = -1
private val viewRect = Rect()
private var touchStarted = false
init {
setTransitionListener(object : MotionLayout.TransitionListener {
override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) {
}
override fun onTransitionStarted(p0: MotionLayout?, p1: Int, p2: Int) {
}
override fun onTransitionChange(p0: MotionLayout, p1: Int, p2: Int, p3: Float) {
}
override fun onTransitionCompleted(p0: MotionLayout, p1: Int) {
touchStarted = false
}
})
context.theme.obtainStyledAttributes(
attributeSet,
R.styleable.SingleViewTouchableMotionLayout,
0, 0).apply {
try {
viewToDetectTouchRes = getResourceId(
R.styleable.SingleViewTouchableMotionLayout_viewToDetectTouch, 0)
} finally {
recycle()
}
}
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
viewToDetectTouch1 = (parent as View).findViewById<View>(viewToDetectTouchRes)
}
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.actionMasked) {
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
touchStarted = false
return super.onTouchEvent(event)
}
}
if (!touchStarted) {
viewToDetectTouch1?.getHitRect(viewRect)
touchStarted = viewRect.contains(event.x.toInt(), event.y.toInt())
}
return touchStarted && super.onTouchEvent(event)
}
}
And add the custom attribute which will be used to declare the View that gonna receives the events to trigger the Transition/animation. Add these styleable to your attrs.xml in your res folder (res/values/attrs.xml)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SingleViewTouchableMotionLayout">
<attr name="viewToDetectTouch" format="reference" />
</declare-styleable>
</resources>
Thats it!! This way we can archive MotionLayout OnSwipe on a specified view.
Layout XML file now will look like this :
<your_package.SingleViewTouchableMotionLayout
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"
app:layoutDescription="@xml/motion_file"
app:viewToDetectTouch="@+id/triggerView"
>
<!-- Notice that 'app:viewToDetectTouch' hold the id of the view we interested -->
<!-- View we interested -->
<View
android:id="@+id/triggerView"
android:layout_width="50dp"
android:layout_height="50dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:background="@color/colorBlack"
/>
</your_package.SingleViewTouchableMotionLayout>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With