规模过渡动画

3

我想为ConstraintLayout中的Scale View元素创建自定义过渡。在AutoTransition.java内部,我们有淡入、调整边界和淡出。因此,执行简单的缩放不会动画化更改。

经过一些解决方法,我能够创建具有缩放功能的自定义过渡。我的目标是创建带有可见性和缩放的过渡集。通过下面的更改,这个动画可以很好地工作,尽管缩放枢轴可能会发生变化。

 //..................... 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>

主要问题在于缩放动画的中心点是零(视图左上角)。我无法更改动画视图的过渡中心点。无论是将此属性添加到View.java还是ConstraintSet.java参数中都不行。因此,问题是如何为此缩放转换更改视图中心点。(作为附加问题,我也想知道如何更改默认的AdjustBounds转换的中心点,其中我们更改了视图的高度/宽度)。


请添加您的 XML 代码。 - Rami Jemli
@RamiJemli 已更新。 - GensaGames
你能解释一下什么是"This View will change Visibility with Text Changes"吗?如果你想让视图变成GONE而不是INVISIBLE,这就有点棘手了。 - Pawel
2个回答

6

尝试在每个动画步骤中重置枢轴。如果您正在寻找中心枢轴,您可以直接删除getWidth(),否则您需要捕获另一个枢轴值并使用它。

尝试这个过渡:

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;
    }
}

如此简单且有效的解决方案。我错过了从大小设置枢轴,并假设使用百分比。谢谢! - GensaGames

2
为了为TransitionManager创建自定义转换,您需要创建自定义的Transition或TransitionSet。例如:
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);

您可以在这里了解有关 TransitionSet 的更多信息,并且在这里了解有关Transition的更多信息。


谢谢提供的信息。我会尝试使用 ConstraintLayout 实现。你有执行比例转换的示例吗? - GensaGames
所以它不起作用。该转换与约束不兼容。这里的问题是,关于更改约束动画。 - GensaGames
你选择了哪种方法?你是否添加了所有应该被动画化的转换和它们的目标(视图)? - Patryk Goworowski
我没有找到创建自定义转换的示例,这适用于约束布局缩放。 - GensaGames

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接