在Android中使用动画更改布局宽度

时间:2019-02-05 07:56:08

标签: android android-layout android-animation

我尝试通过动画更改我的relativeLayout宽度。我的目标是通过动画将WRAP_CONTENT宽度更改为MATCH_PARENT。这是我的源代码

private void setWidthAnimation(View view, int currentHeight, int newHeight) {
    ValueAnimator slideAnimator = ValueAnimator
            .ofInt(currentHeight, newHeight)
            .setDuration(1000);
    slideAnimator.addUpdateListener(animation -> {
        Integer value = (Integer) animation.getAnimatedValue();
        view.getLayoutParams().width = value.intValue();

        view.requestLayout();
    });
    AnimatorSet set = new AnimatorSet();

    set.play(slideAnimator);
    set.setInterpolator(new BounceInterpolator());
    set.start();
    view.setBackgroundColor(Color.RED);
}

我这样叫这个方法

  if (isKeyBoardOpen)
            setWidthAnimation(gifEditableLayout, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
        else
            setWidthAnimation(gifEditableLayout, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);

但是当我运行我的应用程序时,视图的宽度已更改,但没有动画。谁能解释我在做什么错? 谢谢

3 个答案:

答案 0 :(得分:1)

您的代码的主要问题是您实际上没有宽度的实际值。

如果您查看自己的setWidthAnimation()方法,请查看它的显示位置:

ValueAnimator slideAnimator = ValueAnimator
        .ofInt(currentHeight, newHeight)
        .setDuration(1000);

尤其要查看 currentHeight newHeight 。您知道这两个int变量的值是什么吗?

setWidthAnimation(gifEditableLayout, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);

您使用ViewGroup.LayoutParams.WRAP_CONTENTViewGroup.LayoutParams.MATCH_PARENT作为宽度的值。但是,这些都不是视图的实际宽度。

相反,它们只是LayoutParams的静态常量:

  • MATCH_PARENT是一个静态int常量,值为-1

  • WRAP_CONTENT是一个静态int常量,值为-2

因此,您实质上是在告诉ValueAnimator在1秒的时间内从-1到-2或-2到-1的值进行动画处理。

此外,您只是将LayoutParam的宽度设置为-1或-2。幸运的是,这确实实现了View的完成外观,因为View的宽度可以有3种类型的可能性:

  • layoutParams.width = -1; 这与调用FILL_PARENTMATCH_PARENT

  • 相同
  • layoutParams.width = -2; 这与调用WRAP_CONTENT

  • 相同
  • layoutParams.width = ANY_OTHER_INT; :这与直接将宽度设置为此值相同。

但是,不会发生动画。

这样做的原因仅仅是因为ValueAnimator实际上不进行任何动画处理。您可以将其更多地视为一个数字计数器。您已对其进行编码,以在1秒的时间内计算从-1到-2的int值。因此,启动时位于WRAP_CONTENT。下一个可能的int值是-2,它是完成值,因此它将在1秒后精确更新。一秒钟后,它将更新并运行您拥有的代码,该代码将视图的宽度设置为-2。这将立即强制视图为MATCH_PARENT

因此,要解决此问题,您需要将实整数值传递给setWidthAnimation()方法。

答案 1 :(得分:0)

尝试将android:animateLayoutChanges="true"放在父视图(XML)上。 更多信息: https://proandroiddev.com/the-little-secret-of-android-animatelayoutchanges-e4caab2fddec

答案 2 :(得分:0)

我真的不知道您的代码是什么,但是我可以建议您我的选择:将您的亲戚放在Constraint内并使用约束集动画。 启动xml

<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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/rootContainer"
    tools:context=".MainActivity">

    <RelativeLayout
        android:id="@+id/rLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </RelativeLayout>

和代码:

RelativeLayout layout;
ConstraintLayout root;

... 

layout = findViewById(R.id.rLayout);
root = findViewById(R.id.rootContainer);

public void animate() {
    ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams(0, 0);
    layout.setLayoutParams(params);
    ConstraintSet set = new ConstraintSet();
    set.clone(root);
    set.connect(layout.getId(), ConstraintSet.BOTTOM, root.getId(), ConstraintSet.BOTTOM);
    set.connect(layout.getId(), ConstraintSet.TOP, root.getId(), ConstraintSet.TOP);
    set.connect(layout.getId(), ConstraintSet.LEFT, root.getId(), ConstraintSet.LEFT);
    set.connect(layout.getId(), ConstraintSet.RIGHT, root.getId(), ConstraintSet.RIGHT);
    AutoTransition transition = new AutoTransition();
    transition.setDuration(1000);
    TransitionManager.beginDelayedTransition(root, transition);
    set.applyTo(root);
}