Android: FillAfter not working for ScaleAnimation in ImageView - android

I am applying three animations in an ImageView, one after another. I have a AnimationListener for each animation, so inside the onAnimationEnd, I start the next one, so they dont overlap. The animations are this: scale in, fade out and the last one fade in. The fade in animation will restart the scale in animation again, to these animations will be running "forever". What I am trying to achieve is the same effect Twitter has applied to their new home screen, where they keep changing the pictures.
The problem with my animations is that after scaling in the ImageView and before staring the the fade out animation, the ImageView gets reseted and the scale change is lost, even setting fillAfter in the code or in the xml file. Here is the code for handling the animation events:
mAnimationFadeIn = AnimationUtils.loadAnimation(this, R.anim.fade_in);
mAnimationFadeIn.setFillAfter(true);
mAnimationFadeOut = AnimationUtils.loadAnimation(this, R.anim.fade_out);
mAnimationFadeOut.setFillAfter(true);
mAnimationScaleIn = AnimationUtils.loadAnimation(this, R.anim.slow_scale_in);
mAnimationScaleIn.setFillAfter(true);
mAnimationScaleIn.setFillEnabled(true);
mAnimationScaleIn.setFillBefore(false);
mAnimationScaleIn.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {}
#Override
public void onAnimationRepeat(Animation animation) {}
#Override
public void onAnimationEnd(Animation animation) {
mImageView.startAnimation(mAnimationFadeOut);
}
});
mAnimationFadeOut.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {}
#Override
public void onAnimationRepeat(Animation animation) {}
#Override
public void onAnimationEnd(Animation animation) {
mImageView.setImageResource(mImages[++mImageIndex > 2 ? mImageIndex=0 : mImageIndex]);
mImageView.startAnimation(mAnimationFadeIn);
}
});
mAnimationFadeIn.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {}
#Override
public void onAnimationRepeat(Animation animation) {}
#Override
public void onAnimationEnd(Animation animation) {
mImageView.startAnimation(mAnimationScaleIn);
}
});
mImageView.startAnimation(mAnimationScaleIn);
and here are my animations:
scale in:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:duration="9000"
android:fromXScale="1.0"
android:fromYScale="1.0"
android:interpolator="#android:anim/linear_interpolator"
android:pivotX="50.0%"
android:pivotY="50.0%"
android:toXScale="1.1"
android:toYScale="1.1" />
fade in:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromAlpha="0.0"
android:interpolator="#android:anim/linear_interpolator"
android:toAlpha="1.0" />
fade out:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromAlpha="1.0"
android:interpolator="#android:anim/linear_interpolator"
android:toAlpha="0.0" />
Is there a way to keep the scale transformation before starting the fade out animation?
I have tried all the combinations for setFillAfter, setFillBefore and setFillEnabled and no way I can get the scale transformation to be kept after the scale animation is over.
Many thanks
T

do as given below u have to enable it in set tag and than use in either rotate or scale etc...
<?xml version="1.0" encoding="UTF-8"?>
<set android:shareInterpolator="false"
android:fillEnabled="true"
android:fillAfter="true"
xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="359"
android:pivotX="50%"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="1.4"
android:pivotY="50%"
android:fillAfter="true"
android:fillEnabled="true"
android:duration="2000" />
<scale
android:interpolator="#android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="1.4"
android:pivotX="50%"
android:pivotY="50%"
android:fillEnabled="true"
android:fillAfter="true"
android:duration="2000" />
</set>

Related

Android animation "blink" when repeat

In my application I have this animation
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:shareInterpolator="true">
<alpha
android:duration="1000"
android:startOffset="2000"
android:fromAlpha="0"
android:toAlpha="1"/>
<scale
android:duration="400"
android:startOffset="4000"
android:fromXScale="1"
android:fromYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.9"
android:toYScale="0.9"/>
<scale
android:duration="400"
android:startOffset="4400"
android:fromXScale="0.9"
android:fromYScale="0.9"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1"/>
<alpha
android:duration="1000"
android:startOffset="5800"
android:fromAlpha="1"
android:toAlpha="0"/>
</set>
Generally it shows image, make "press" gesture and hide it. What I want is run this animation in infinite loop. Setting parameter repeatCount doesn't work. Only way I found is to start animation again in animation listener.
final Animation pointerAnim = AnimationUtils.loadAnimation(this, R.anim.pointer);
pointerAnim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(final Animation animation) {}
#Override
public void onAnimationEnd(final Animation animation) {
pointerView.startAnimation(pointerAnim);
}
#Override
public void onAnimationRepeat(final Animation animation) {}
});
pointerView.startAnimation(pointerAnim);
But here comes my problem. Between end and new start animation, the image "blink" (appeared and disappeared in short moment) and I don't know how to prevent this. Using fillAfter doesn't work. Also setting appropriate visibility in listener doesn't work. Note that target API is 10.
I'll be glad for any advice
This was surprisingly tricky, but here's an answer that seems to work and avoid the blinking. Break the animation up into two parts and set two animation listeners so that when each of them finish, they trigger the other one to start. It looks as follows:
pointer_fade_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:shareInterpolator="true">
<alpha
android:duration="1000"
android:startOffset="2000"
android:fromAlpha="0"
android:toAlpha="1"/>
<scale
android:duration="400"
android:startOffset="4000"
android:fromXScale="1"
android:fromYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.9"
android:toYScale="0.9"/>
</set>
pointer_fade_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:duration="400"
android:startOffset="0"
android:fromXScale="0.9"
android:fromYScale="0.9"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1"/>
<alpha
android:duration="1000"
android:startOffset="1400"
android:fromAlpha="1"
android:toAlpha="0"/>
</set>
Then the code:
final Animation pointerFadeInAnim = AnimationUtils.loadAnimation(this, R.anim.pointer_fade_in);
final Animation pointerFadeOutAnim = AnimationUtils.loadAnimation(this, R.anim.pointer_fade_out);
pointerFadeInAnim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(final Animation animation) {}
#Override
public void onAnimationEnd(final Animation animation) {
pointerView.startAnimation(pointerFadeOutAnim);
}
#Override
public void onAnimationRepeat(final Animation animation) {}
});
pointerFadeOutAnim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {}
#Override
public void onAnimationEnd(Animation animation) {
pointerView.startAnimation(pointerFadeInAnim);
}
#Override
public void onAnimationRepeat(Animation animation) {}
});
pointerView.startAnimation(pointerFadeInAnim);
Hope this works for you!
Did you try combining both repeatMode and repeatCount attributes like in the following example
<scale
android:fromXScale="0.0"
android:toXScale="1.0"
android:fromYScale="0.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="2000"
android:repeatCount="infinite"
android:repeatMode="restart"
/>
Hope it has helped
Maybe it's just a workaround that won't be applicable in your case, but would it be possible to offset the entiere animation, so that it starts at 3000 ? (Thus, when alpha=1.0)
(Well, after some thought, I'm pretty sure you can't do that, because the alpha transition should be the first when the object first appears on screen)
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:shareInterpolator="true">
<scale
android:duration="400"
android:startOffset="1000"
android:fromXScale="1"
android:fromYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.9"
android:toYScale="0.9"/>
<scale
android:duration="400"
android:startOffset="1400"
android:fromXScale="0.9"
android:fromYScale="0.9"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1"/>
<alpha
android:duration="1000"
android:startOffset="2800"
android:fromAlpha="1"
android:toAlpha="0"/>
<alpha
android:duration="1000"
android:startOffset="5800"
android:fromAlpha="0"
android:toAlpha="1"/>
</set>

Animate object out of the screen and keep it there

How can I move an object out of the screen?
This is how I move the TextView from under the screen into the screen.
slide_up_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="100%" android:toYDelta="0%" android:duration="500" android:fillAfter="true"/>
</set>
This is how I move it out of the screen:
slide_down_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="0%" android:toYDelta="100%" android:duration="500" android:fillAfter="true"/>
</set>
But the TextView appears again. Why?
That is because it renders it again after the animation and will actually place the TextView to its default position from the screen/layout.
solution:
You need to add a listener and set the visibility of your TextView to gone or invisible at the end of the listener.
animation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) { }
#Override
public void onAnimationEnd(Animation animation) {
You_text_view.setVisibility(View.INVISIBLE);
}
#Override
public void onAnimationRepeat(Animation animation) { }
});

Making textView loop a growing and shrinking animation

I am trying to make a TextView grow and then shrink. This process should be repeated infinitely. How do I achieve that? My scale.xml looks like this:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:fromXScale="1.0"
android:fromYScale="1.0"
android:toXScale="2.0"
android:toYScale="2.0"
android:duration="1400" />
</set>
Here's my animation method:
public void runAnimation() {
Animation a = AnimationUtils.loadAnimation(this, R.anim.scale);
a.setRepeatMode(Animation.REVERSE);
a.setRepeatCount(Animation.INFINITE);
a.reset();
textView.clearAnimation();
textView.startAnimation(a);
}
Now my problem is that the TextView grows, but then immediately reverses to the starting appereance. Why won't it go reverse, shrink and repeat the process?
Try this :
public void runAnimation() {
Animation a = AnimationUtils.loadAnimation(this, R.anim.scale);
a.setRepeatMode(Animation.REVERSE);
a.setRepeatCount(-1);
textView.clearAnimation();
textView.startAnimation(a);
}
EDIT
Here is my own code that is working right now :
Call animate like animate(textView)
public void animate (View view) {
mAnimation = new ScaleAnimation(0.3f,0.5f,0.3f,0.5f,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.45f);
mAnimation.setDuration(300);
mAnimation.setRepeatCount(-1);
mAnimation.setRepeatMode(Animation.REVERSE);
mAnimation.setInterpolator(new AccelerateInterpolator());
mAnimation.setAnimationListener(new Animation.AnimationListener(){
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
view.setAnimation(mAnimation);
}
Try this found on some blog. Works perfect for me.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator">
<scale
android:fromXScale="0.0"
android:toXScale="1.0"
android:fromYScale="0.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="2000" />
</set>
Here is a simple way to do so
ObjectAnimator scaleDown = ObjectAnimator.ofPropertyValuesHolder(textView,
PropertyValuesHolder.ofFloat("scaleX", 2.0f),
PropertyValuesHolder.ofFloat("scaleY", 2.0f));
scaleDown.setDuration(410);
scaleDown.setRepeatCount(ObjectAnimator.INFINITE);
scaleDown.setRepeatMode(ObjectAnimator.REVERSE);
scaleDown.start();
Hope it helps.
In your animation XML file add:
android:repeatCount="infinite"
And on your animation activity:
textmain.startAnimation(animationMainText);
animationMainText.setRepeatMode(Animation.REVERSE);

View animation interact with another view animation

I have 2 imageview (a imageview for a pen image, and a imageview for a line, both are drawable), that each one has it own view animation that works perfectly.
my problem is that when I start the animation for the pen I want it to interact and animate the drawing of the line in the other view animation (I want that it will show as the pen is drawing the line), how do I do that?
my xml for animation for the pen imageview is:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="0%p"
android:toXDelta="100%p"
android:fromYDelta="-50%p"
android:toYDelta="-50%p"
android:duration="2000"/>
</set>
my xml for animation for the line imageview is:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:pivotX="0%"
android:pivotY="50%"
android:fromXScale="0%"
android:toXScale="100%"
android:fromYScale="1.0"
android:toYScale="1.0"
android:fillAfter="true"
android:duration="2000"
android:interpolator="#android:anim/linear_interpolator"
/>
please help!
I believe this can be done with the help of animationListener. Add an animationListener for the pen's animation. In onAnimationStart method do lineImage.startAnimation(lineAnimation);
Sample:
penAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
lineImage.startAnimation(lineAnimation);
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});

change image on translateanimation on android

I implement the translateAnimation to a imageview.
it Successfully animatated.
One translate is moving up and another one is moving down. i need to change image when start second translate.
My code is:
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/accelerate_decelerate_interpolator"
android:shareInterpolator="true">
<translate
android:fromXDelta="0%" android:toXDelta="0%p"
android:fromYDelta="0%" android:toYDelta="20%"
android:drawable="#drawable/bs_bunny1"
android:duration="2000" android:startOffset="100"/>
<translate
android:fromXDelta="0%" android:toXDelta="0%p"
android:fromYDelta="0%p" android:toYDelta="-20%p"
android:duration="3000" android:startOffset="100"/></set>
I set the above animation to the imageview.
But i want to chage the image when start to load the second translate.. How to do it.
You need to break it up into two animations, and register a Animation.AnimationListener to the first translate animation. On Animation.AnimationListener's onAnimationEnd(Animation animation) callback, do the image change and then start the second animation, like thus:
translate.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
view.setImageResource(resId);
view.startAnimation(translate2);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});

Categories

Resources