Reputation: 2243
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
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
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