Reputation: 439
I know how to moving object (imageview, for example) to end from start point,
((MotionLayout)findViewById(R.id.motionLayout)).transitionToEnd();
but how move object to keyPosition
, when i clicked a button?
And if its impossible, which tools i must use, to do this?
motion layout code:
motion_06_keyframe.xml
<androidx.constraintlayout.motion.widget.MotionLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/motionLayout"
app:layoutDescription="@xml/scene_06"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="@+id/button"
android:background="@color/colorAccent"
android:layout_width="64dp"
android:layout_height="64dp" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="36dp"
android:text="Button"
android:onClick="lol"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.47"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.motion.widget.MotionLayout>
scene_06.xml
<MotionScene
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">
<Transition
motion:constraintSetStart="@+id/start"
motion:constraintSetEnd="@+id/end"
motion:duration="1000"
motion:motionInterpolator="linear">
<OnSwipe
motion:touchAnchorId="@+id/button"
motion:touchAnchorSide="right"
motion:dragDirection="dragRight" />
<KeyFrameSet>
<KeyPosition
motion:keyPositionType="pathRelative"
motion:percentY="-0.25"
motion:framePosition="50"
motion:motionTarget="@id/button"/>
</KeyFrameSet>
</Transition>
<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@id/button"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginStart="8dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent">
<CustomAttribute
motion:attributeName="BackgroundColor"
motion:customColorValue="#D81B60"/>
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@id/button"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginEnd="8dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintTop_toTopOf="parent">
<CustomAttribute
motion:attributeName="BackgroundColor"
motion:customColorValue="#9999FF"/>
</Constraint>
</ConstraintSet>
</MotionScene>
Upvotes: 1
Views: 2556
Reputation: 491
KeyPosition
defines the state the animation should go through, u can't stop the transition there with default tools.
The best choice is to divide your transition into two:
1) start to middle
2) middle to end
But the thing is, MotionLayout
won't know where you want to transition to if the current state is middle. It takes the first transition in the xml file, so you will have to change it manually to perform the second transition.
View button; // the button
boolean weWantTransitionToEnd; // depends on your logic, you can throw it away
MotionLayout motionLayout; // the layout
button.setOnClickListener(view -> {
switch (motionLayout.getCurrentState()) {
case R.id.start:
motionLayout.transitionToEnd();
break;
case R.id.middle:
if (weWantTransitionToEnd) {
motionLayout.setTransition(R.id.middle, R.id.end);
motionLayout.transitionToEnd();
} else {
motionLayout.setTransition(R.id.start, R.id.middle);
motionLayout.transitionToStart();
}
break;
case R.id.end:
motionLayout.transitionToStart();
break;
}
});
The user won't be able to swipe this correctly though.
If you want the user to be able to swipe it in both directions and this square to stick in the middle in some cases, you will have to extend MotionLayout
class, leave only one transition (from start to end) and implement your own logic in it.
The key would be overriding OnTouchEvent(MotionEvent event)
and dispatchTouchEvent(MotionEvent event)
methods.
private boolean isThumbDown;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
isThumbDown = true;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
isThumbDown = false;
break;
}
return super.dispatchTouchEvent(ev);
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
if (getProgress() > 0.47f && getProgress() < 0.53f && !isThumbDown) return false;
return super.onTouchEvent(event);
}
That way the transition could stop somewhere in between 47% and 53% in the middle and the user would be able to continue swiping in both directions.
Upvotes: 2