I want to create custom Transition for the Scale View elements in the ConstraintLayout. Inside the AutoTransition.java. We have Fade In, AdjustBounds and Fade Out. So performing simple Scale doesn't animate changes.
After some workaround I was able to Create custom Transition with Scale. And my point, it's to create Transition Set with Visiblity and Scale. With changes below this animation works well, despite Scale Pivot.
//..................... General method from Custom Scale Transition
@Nullable
@Override
public Animator createAnimator(@NonNull ViewGroup sceneRoot, @Nullable TransitionValues startValues,
@Nullable TransitionValues endValues) {
if (null == startValues || null == endValues) {
return null;
}
final View view = endValues.view;
final float startX = (float) startValues.values.get(PROPNAME_SCALE_X);
final float endX = (float) endValues.values.get(PROPNAME_SCALE_X);
final float startY = (float) startValues.values.get(PROPNAME_SCALE_Y);
final float endY = (float) endValues.values.get(PROPNAME_SCALE_Y);
final AnimatorSet set = new AnimatorSet();
final ValueAnimator animatorX = ValueAnimator.ofFloat(startX, endX);
animatorX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final float value = (float) animation.getAnimatedValue();
view.setScaleX(value);
}
});
final ValueAnimator animatorY = ValueAnimator.ofFloat(startY, endY);
animatorY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final float value = (float) animation.getAnimatedValue();
view.setScaleY(value);
}
});
set.playTogether(animatorX, animatorY);
return set;
}
//..................... Complete Set Transitions
public class ScaleVisibility extends TransitionSet {
public ScaleVisibility() {
setOrdering(ORDERING_TOGETHER);
addTransition(new Fade()).
addTransition(new Scale());
}
}
//..................... Code for starting Animation.
mConstraintSet.clone(mConstraintLayout);
Transition transition = new ScaleVisibility();
transition.setDuration(3000);
mConstraintSet.setScaleX(item.resource, item.scale);
mConstraintSet.setScaleY(item.resource, item.scale);
mConstraintSet.setTransformPivot(item.resource, 0.5f, 0.5f);
mConstraintSet.setVisibility(item.resource, item.visibility);
TransitionManager.beginDelayedTransition(mConstraintLayout, transition);
mConstraintSet.applyTo(mConstraintLayout);
//..................... Main XML. Trying to Animate input_send_button
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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"
android:id="@+id/fragment_input_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:id="@+id/input_background"
android:layout_width="match_parent"
android:layout_height="@dimen/chat_input_panel_height"
android:background="@color/white"
app:layout_constraintBottom_toBottomOf="parent"/>
<!--This View will change Visibility with Text Changes-->
<ImageButton
android:id="@+id/input_send_button"
android:layout_width="@dimen/chat_input_panel_height"
android:layout_height="0dp"
android:background="@android:color/transparent"
android:src="@drawable/chat_send"
android:tint="@color/primary"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@+id/input_background"
app:layout_constraintRight_toRightOf="@+id/input_background"
app:layout_constraintTop_toTopOf="@+id/input_background"
tools:ignore="ContentDescription"
tools:visibility="visible"/>
</android.support.constraint.ConstraintLayout>
Main issue here, it's Scale animation Pivot, which is zero (top left corner of view). And I cannot change Transition pivot for Animated view. Neither with adding this property to the View.java nor ConstraintSet.javaparameters. So question it's how to change View Pivot for this Scale Transition. (As additional question, I was interested with changing Pivot for the default AdjustBounds Transition, where we changing view Height/Width).
Try resetting the pivot on each animation step. If you're looking for center pivot you can just slash through getWidth(), otherwise you need to capture another pivot value and use it.
Try this transition:
public class ScaleTransition extends Transition {
private final static String PROPNAME_SCALE_X = "PROPNAME_SCALE_X";
private final static String PROPNAME_SCALE_Y = "PROPNAME_SCALE_Y";
@Override
public void captureStartValues(TransitionValues transitionValues) {
captureValues(transitionValues);
}
@Override
public void captureEndValues(TransitionValues transitionValues) {
captureValues(transitionValues);
}
private void captureValues(TransitionValues values){
values.values.put(PROPNAME_SCALE_X, values.view.getScaleX());
values.values.put(PROPNAME_SCALE_Y, values.view.getScaleY());
}
@Override
public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues) {
if(endValues == null || startValues == null)
return null; // no values
float startX = (float) startValues.values.get(PROPNAME_SCALE_X);
float startY = (float) startValues.values.get(PROPNAME_SCALE_Y);
float endX = (float) endValues.values.get(PROPNAME_SCALE_X);
float endY = (float) endValues.values.get(PROPNAME_SCALE_Y);
if(startX == endX && startY == endY)
return null; // no scale to run
final View view = startValues.view;
PropertyValuesHolder propX = PropertyValuesHolder.ofFloat(PROPNAME_SCALE_X, startX, endX);
PropertyValuesHolder propY = PropertyValuesHolder.ofFloat(PROPNAME_SCALE_Y, startY, endY);
ValueAnimator valAnim = ValueAnimator.ofPropertyValuesHolder(propX, propY);
valAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
view.setPivotX(view.getWidth()/2f);
view.setPivotY(view.getHeight()/2f);
view.setScaleX((float) valueAnimator.getAnimatedValue(PROPNAME_SCALE_X));
view.setScaleY((float) valueAnimator.getAnimatedValue(PROPNAME_SCALE_Y));
}
});
return valAnim;
}
}
In order to create a custom transition(s) for TransitionManager you need to create a custom Transition or TransitionSet. For example:
TransitionSet transitionSet = new TransitionSet();
//your types of transitions
Transition first = new ChangeBounds();
Transition second = new Fade();
first.addTarget(firstView);
second.addTarget(secondView);
//Add your transitions to TransitionSet
transitionSet.addTransition(first).addTransition(second);
//Start transitions
TransitionManager.beginDelayedTransition(layout, transitionSet);
You can learn more about TransitionSet here and about Transition here
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