BekaKK
BekaKK

Reputation: 2243

change layout width with animation in android

I try to change my relativeLayout width with animation.My goal is to change WRAP_CONTENT width to MATCH_PARENT with animation.Here is a my source code

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

I'm calling this method like this

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

But when I run my app, view's width has changed but without animation. can anyone explain me what am I doing wrong? Thanks

Upvotes: 1

Views: 3413

Answers (2)

Jackey
Jackey

Reputation: 3234

Your code's main problem is that you don't actually have the real values for the width.

If you look at your setWidthAnimation() method, look where it says:

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

In particular, look at currentHeight and newHeight. Do you know what are the values for these two int variables?

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

You're using ViewGroup.LayoutParams.WRAP_CONTENT and ViewGroup.LayoutParams.MATCH_PARENT as the values for the width. However, neither of these are the actual width of your View.

Instead, they're just static constants of LayoutParams:

  • MATCH_PARENT is a static int constant with a value of -1

  • WRAP_CONTENT is a static int constant with a value of -2

So you're essentially telling the ValueAnimator to animate from the value of either -1 to -2 or -2 to -1 in a duration of 1 second.

Additionally, you're just setting -1 or -2 to the LayoutParam's width. Luckily for you, this does achieve the finished appearance of your View, because a View's width can have 3 types of possibilities:

  • layoutParams.width = -1; This is the same as calling FILL_PARENT or MATCH_PARENT

  • layoutParams.width = -2; This is the same as calling WRAP_CONTENT

  • layoutParams.width = ANY_OTHER_INT; This is the same as directly setting the width to this value.

However, no animation will happen.

The reason for this is simply because the ValueAnimator actually doesn't do any animating. You can think of it more as a number counter. You've coded it to count int values from -1 to -2 over the timespan of 1 second. So when it starts, it's at WRAP_CONTENT. The next possible int value is -2, which is the finished value, so it'll update exactly after 1 second. One second later, it updates and runs the code you have which is setting the View's width to -2. This instantly forces the View to be MATCH_PARENT.

So to fix this, you need to pass the real integer values to your setWidthAnimation() method.

Upvotes: 1

Vadim Eksler
Vadim Eksler

Reputation: 887

i really don't know what with your code, but I can suggest to you my option: put your relative inside Constraint and work with constraint set animation. Start 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>

And code:

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

Upvotes: 0

Related Questions