Reputation: 153
I'm trying to create (what I thought was) a relatively simple Animation in Android. Namely, I want to get a certain TextView to scale down to 0 and back up to 1 on the click of a button. What actually happens when I click the button is the TextView immediately scales down to 0 (no animation) and then animates only the scaling back to 1.
After some failed attempts using only the View.animate() methods, I resorted to Animator and AnimatorSet and defining the animations in XML like below:
scale_down.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="scaleX"
android:valueFrom="0"
android:valueTo="1"
android:duration="300"/>
<objectAnimator
android:propertyName="scaleY"
android:valueFrom="0"
android:valueTo="1"
android:duration="300"/>
</set>
scale_up.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="scaleX"
android:valueFrom="1"
android:valueTo="0"
android:duration="300"/>
<objectAnimator
android:propertyName="scaleY"
android:valueFrom="1"
android:valueTo="0"
android:duration="300"/>
</set>
Code in the animate() method which is called from the onClick() method
private void animate() {
Animator scaleTextDown = AnimatorInflater.loadAnimator(this, R.animator.scale_down);
scaleTextDown.setTarget(mFactTextView);
Animator scaleTextUp = AnimatorInflater.loadAnimator(this, R.animator.scale_up);
scaleTextDown.setTarget(mFactTextView);
AnimatorSet setScaleDownAndUp = new AnimatorSet();
setScaleDownAndUp.playSequentially(scaleTextDown, scaleTextUp);
setScaleDownAndUp.start();
}
While I was attempting to create the intended animation using the simple View.animate() methods I got it to work using a handler to add a break inside the onClick() method like below, but I doubt that's the "right" way to do it.
public void onClick(View view) {
//...
mFactTextView.animate().scaleX(0).scaleY(0).setDuration(300).start();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mFactTextView.animate().scaleX(1).scaleY(1).setDuration(300).start();
}
}, 300);
//...
}
So this simple code above obviously works without the use of any XML etc.
I'm relatively new to Android and I've started exploring Animations so I'm asking if there is actually a "better" way to chain these animations one after another? I mean the existence of the method playSequentially() suggests that there should be a way to make this work without a Handler. Maybe the issue is that both animations concern the same object, but I imagine this isn't a rare use case. Though it's the same type of animation just in the opposite direction, so maybe this is a rarer use case, but still.
EDIT: I updated the XML code to correctly reflect the intended scaling (thanks azizbekian), and it still doesn't work as expected. I'm getting the opposite behavior now. On initial click of the button, the text now simply scales down to 0 and is lost. On subsequent clicks it briefly shows up at full size (no scaling animation), then animates scaling down to 0, and it's lost again.
Technically, in both the initial XML files and the updated ones (below), only the first animation was actually happening, at least visually - the one where scale_down.xml is used as source for the Animator.
scale_down.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="scaleX"
android:valueFrom="1"
android:valueTo="0"
android:duration="300"/>
<objectAnimator
android:propertyName="scaleY"
android:valueFrom="1"
android:valueTo="0"
android:duration="300"/>
</set>
scale_up.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="scaleX"
android:valueFrom="0"
android:valueTo="1"
android:duration="300"/>
<objectAnimator
android:propertyName="scaleY"
android:valueFrom="0"
android:valueTo="1"
android:duration="300"/>
</set>
Upvotes: 2
Views: 6426
Reputation: 62189
You do not need handlers, because there is withEndAction()
API:
mFactTextView.animate().scaleX(0).scaleY(0).setDuration(300).withEndAction(new Runnable() {
@Override
public void run() {
mFactTextView.animate().scaleX(1).scaleY(1).setDuration(300);
}
});
There is no need to call start()
explicitly, the animation will start on next frame.
And the reason why xml
won't work for you, is that you have incorrectly specified start and end values. scale_down
animation should start from 1 and end up to 0, and scale_up
should start from 0 and animate to 1.
Update
You are performing setTarget()
on same instance twice. Change second scaleTextDown.setTarget()
to scaleTextUp.setTarget()
.
Upvotes: 13