pTak
pTak

Reputation: 63

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

Upvotes: 4

Views: 1439

Answers (3)

Lewis McGeary
Lewis McGeary

Reputation: 7922

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!

Upvotes: 2

Orab&#238;g
Orab&#238;g

Reputation: 11992

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>

Upvotes: 0

Aur&#233;lien Leloup
Aur&#233;lien Leloup

Reputation: 166

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

Upvotes: 0

Related Questions