Androidアニメーションが繰り返されない


85

数回(または無限に)繰り返される単純なアニメーションを作成しようとしています。
それはそうandroid:repeatCount動作しません!
これが私のアニメーションリソースです/res/anim/first_animation.xml

<?xml version="1.0" encoding="utf-8"?>
<set
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false"
    android:repeatCount="infinite"
    >
    <scale
        android:interpolator="@android:anim/decelerate_interpolator"
        android:duration="500"
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:toXScale="1.2"
        android:toYScale="1.2"
        android:pivotX="50%"
        android:pivotY="50%"
        android:fillAfter="false" />
    <scale
        android:interpolator="@android:anim/accelerate_interpolator"
        android:startOffset="500"
        android:duration="500"
        android:fromXScale="1.2"
        android:fromYScale="1.2"
        android:toXScale="1.0"
        android:toYScale="1.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:fillAfter="false" />
</set>

まず、500ミリ秒で画像を1.0から1.2サイズに拡大縮小する必要があります。
そして、500ミリ秒で1.0にスケールバックします。
これが私がそれをどのように使っているかです:

Animation firstAnimation = AnimationUtils.loadAnimation(this, R.anim.first_animation);
imgView.startAnimation(firstAnimation);

1サイクルで終了します。
スケールアップしてからスケールダウンして停止します。

どうすればこれを意図したとおりに機能させることができますか?


JavaコードのimgViewとは何ですか?
clifgray 2013

回答:


63

更新: 2011年9月に、Androidエンジニアがこの問題の大部分を修正しました。XMLで無視された属性は、(何らかの理由で意図的に)無視されることを除いて、機能するようにrepeatCountなりましfillEnabledた。これは、AnimationSet残念ながらそれでも繰り返すのは簡単ではないことを意味します。

詳細については、更新されたドキュメントの概要を参照してください(無視される属性、機能する属性、および子に渡される属性について説明しています)。そして、何のより深い理解のためにfillAfterfillBeforefillEnabled実際に行う、それについてエンジニアの(チェットハーゼ)のブログ記事を参照してくださいここに


元の回答

Pavelや他の人の答えを拡張するために:<set>タグがばかげてバグがあるのは事実です。とrepeatCount他の多くの属性を正しく処理できません。

私はそれが何に対処できるか、何ができないかを理解するために数時間を費やし、ここにバグレポート/問題を提出しました:問題17662

要約すると(これはAnimationSetsに関係します):

setRepeatCount()/ android:repeatCount

この属性(およびrepeatMode)は、コードまたはXMLでは機能しません。これにより、アニメーションのセット全体を繰り返すことが困難になります。

setDuration()/ android:duration

これをコードWORKSのAnimationSetに設定します(子アニメーションのすべての期間をオーバーライドします)が、XMLのタグに含まれている場合は設定しません

setFillAfter()/ android:fillAfter

これは、タグのコードとXMLの両方で機能します。不思議なことに、fillEnabledをtrueに設定しなくても機能するようになりました。

setFillBefore()/ android:fillBefore

コードとXMLの両方で効果がない/無視されているようです

setFillEnabled()/ android:fillEnabled

コードとXMLの両方で効果がない/無視されているようです。fillEnabledを含めたり、fillEnabledをfalseに設定しなくても、fillAfterを機能させることができます。

setStartOffset()/ android:startOffset

これはコードでのみ機能し、XMLでは機能しません。


48

<set>タグのクラスAnimationSetにバグのある実装があることがわかりました。repeatCount
を正しく処理できません
私たちにできることは、repeatCount<scale>タグに直接設定することです。

このXMLリソースはうまく機能しています。

<?xml version="1.0" encoding="utf-8"?>
<scale
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:duration="200"
    android:fromXScale="1.0"
    android:fromYScale="1.0"
    android:toXScale="1.05"
    android:toYScale="1.05"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatMode="reverse"
    android:fillAfter="false"
    android:repeatCount="24"
/>

残念ながら、これは一度に1つのアニメーションに制限されています。
この方法でアニメーションのシーケンスを定義することはできません...


セットで2つのアニメーションを実行していますが、問題はありません。あなたが話している問題について教えてください。どのバグ?現在
1.6SDKに

xmlでrepeatCountを宣言することは機能しますが、コードでは機能しません
onmyway1 3319

39

属性を含める必要があります

android:repeatCount="infinite"

しかし、「セット」ではなく「スケール」アニメーションでは


1
しかし、これらのアニメーションは、前のアニメーションが完了するのを待ちますか?ありがとう
filthy_wizard 2016年

おかげで、これはうまくいきました!プログラムで設定することは、何らかの理由で行われませんでした。
チェリーウェーブ

ありがとう!これはうまくいきました。しかし、それは継続的です。これを5秒ごとに言うことは可能ですか?
d34th4ck3r 2017年

32

繰り返しアニメーションを取得するために、アニメーションリスナーを利用し、終了時にアニメーションを再度呼び出しました。これは、ブラケット付きのアニメーションのように焦点を合わせるカメラレチクルを実行します。

これがアニメーションレイアウトxmlです

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
    android:fromXScale="1.0"
    android:toXScale=".7"
    android:fromYScale="1.0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toYScale=".7"
    android:duration="1000"/>
<scale 
    android:duration="1000"
    android:fromXScale=".7"
    android:toXScale="1.0"
    android:fromYScale=".7"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toYScale="1.0"
    android:startOffset="1000"/>

</set>

これがJavaコードです

 public void startAnimation() {

            View brackets = findViewById(R.id.brackets);
            brackets.setVisibility(View.VISIBLE);

            Animation anim = AnimationUtils.loadAnimation(BuzzFinderActivity.this, R.anim.crosshair_focusing);
            anim.setAnimationListener(new AnimationListener() {

                @Override
                public void onAnimationEnd(Animation arg0) {
                    Animation anim = AnimationUtils.loadAnimation(BuzzFinderActivity.this, R.anim.crosshair_focusing);
                    anim.setAnimationListener(this);
                    brackets.startAnimation(anim);

                }

                @Override
                public void onAnimationRepeat(Animation arg0) {
                    // TODO Auto-generated method stub

                }

                @Override
                public void onAnimationStart(Animation arg0) {
                    // TODO Auto-generated method stub

                }

            });


            brackets.startAnimation(anim);
}

2
正解です。すべてのデバイスおよびOSレベルでの作業
2015

それも役に立ちましたが、Endメソッドからこれらの2行を削除しましたAnimation anim = AnimationUtils.loadAnimation(BuzzFinderActivity.this、R.anim.crosshair_focusing); anim.setAnimationListener(this);
aida 2016

10

私も同じ問題に直面していました..XMlファイルにandroid:repeatCount = "infinite"を含めました..今は正常に動作しています...

  <translate 
           android:fromXDelta="0"
           android:toXDelta="80"
           android:duration="1000"
           android:repeatCount="infinite"   
           android:repeatMode="reverse" 
           android:pivotX="50%"
           android:pivotY="50%"                             
           android:fillAfter="true"/>


9

このコードを試すことができます。コードに次を追加するだけです。

firstAnimation.setRepeatCount(5);

これにより、アニメーションが一定時間繰り返されます

firstAnimation.setRepeatCount(Animation.INFINITE);
firstAnimation.setRepeatMode(Animation.INFINITE);

これにより、アニメーションが無期限に繰り返されます。


4
repeatModeRESTARTまたはREVERSE
xinthink 2014年

それはまさに私が望むものであり、動的に無限大に設定するように設定します。
Varun Chaudhary 2016年

2
setRepeatはcode.google.com/p/android/issues/detail?id=17662に従って機能しません
ElliotM

4

ダニエルのコードを使用してアニメーションを正確な回数表示しようとしましたが、問題が発生しました。アニメーションは、n回の予想で、約n / 2回表示されました。

だから私はダニエルのコードを変更しました:

//...
@Override
public void onAnimationEnd(Animation arg0) {
    mCurrentCount++;
    if (mCurrentCount < REPEAT_COUNT) {  
        Animation anim = AnimationUtils.loadAnimation(BuzzFinderActivity.this, R.anim.crosshair_focusing);
        anim.setAnimationListener(this);
        brackets.post(new Runnable() {
            @Override
            public void run() {
                brackets.startAnimation(anim);
            }
        }  
    } 
}
//... 

上記のバリアントを使用すると、アニメーションはREPEAT_COUNT回正確に表示されます。これは、View.post()メソッドが、前のアニメーションに関連するすべてのアクションの終了後に新しいアニメーションを開始する機能を提供するためです。


3

以下に提案したxmlコードに1行だけ追加する必要があります。

<scale
    android:duration="500"
    android:fromXScale="1.0"
    android:fromYScale="1.0"
    android:toXScale="1.2"
    android:toYScale="1.2"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite" // just add this one line 
    android:fillAfter="false"
    />
</set>

2

android sdkバージョン4.0.3の場合:

与えられたアニメーション要素で:

android:repeatCount = "-1"

無限のアニメーションになります。


ありがとう!4.2では回避策なしで
正常に動作し

2

次のクラスをプロジェクトに追加します。

import android.view.View;
import android.view.animation.Animation;

public class AnimationRepeater implements Animation.AnimationListener
{
    private View view;
    private Animation animation;
    private int count;

    public AnimationRepeater(View view, Animation animation)
    {
        this.view = view;
        this.animation = animation;
        this.count = -1;
    }

    public AnimationRepeater(View view, Animation animation, int count)
    {
        this.view = view;
        this.animation = animation;
        this.count = count;
    }

    public void start()
    {
        this.view.startAnimation(this.animation);
        this.animation.setAnimationListener(this);
    }

    @Override
    public void onAnimationStart(Animation animation) { }

    @Override
    public void onAnimationEnd(Animation animation)
    {
        if (this.count == -1)
            this.view.startAnimation(animation);
        else
        {
            if (count - 1 >= 0)
            {
                this.animation.start();
                count --;
            }
        }
    }

    @Override
    public void onAnimationRepeat(Animation animation) { }
}

ビューの無限ループの場合は、次のようにします。

Animation a = AnimationUtils(Context, R.anim.animation);
new AnimationRepeater(View, a).start();

アニメーションをN回だけ繰り返す場合は、次の手順を実行します。

Animation a = AnimationUtils(Context, R.anim.animation);
new AnimationRepeater(View, a, int N).start();

Nは繰り返し回数を表します。


2

android:repeatMode="reverse"以前、プロジェクトでこの問題を使用して解決しました。

<scale
    android:interpolator="@android:anim/decelerate_interpolator"
    android:duration="500"
    android:fromXScale="1.0"
    android:fromYScale="1.0"
    android:toXScale="1.2"
    android:toYScale="1.2"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatMode="reverse"
    android:repeatCount="infinite" />

1

私はほとんどの作業をプログラムで行い、これには遅れるか非効率的かもしれませんが、これは繰り返しアニメーションセットの目標を達成しました(2つの交互のアニメーションセットもあります)。このコードは、1つの画像をフェードインし、一時停止してからフェードアウトし、別の画像をフェードインし、一時停止してフェードアウトし、最初の画像を元に戻す(すすぎと繰り返し)だけです。私は最初にImageviewsを定義しました:

    final ImageView purple = (ImageView)findViewById(R.id.purp);
    final ImageView yellow = (ImageView)findViewById(R.id.yell);
    purple.setVisibility(View.INVISIBLE);
    yellow.setVisibility(View.INVISIBLE);

次に、各アニメーションをいつ開始および停止するかを処理するために、2つのタイマー、タスクタイマーとハンドラーを作成しました。

    Timer p = new Timer();
    TimerTask pu = new TimerTask() {
        public void run() {
                handler1.post(new Runnable() {
                        public void run() 
                        {
                           fadein(purple);
                        }
               });
        }};
        p.schedule(pu, 6000, 12000);

    final Handler handler2 = new Handler();

    Timer y = new Timer();
    TimerTask ye = new TimerTask() {
        public void run() {
                handler2.post(new Runnable() {
                        public void run() 
                        {
                           fadein(yellow);
                        }
               });
        }};

        y.schedule(ye, 0, 12000);

最後に、アニメーションを追加してアニメーションセットを作成するのではなく、アニメーションリスナーを使用して、各アニメーションをいつ開始するかを決定します。

public void fadein (final ImageView image)
{
    Animation anim = new AlphaAnimation(0, 1);

    anim.setDuration(2000);

    image.startAnimation(anim);
    anim.setAnimationListener(new AnimationListener() {
        public void onAnimationEnd(Animation animation) 
        {
            image.clearAnimation();
            image.invalidate();
            pause(image);

        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onAnimationStart(Animation animation) {
            // TODO Auto-generated method stub

        }
    });
}    
public void pause (final ImageView image)
{
    Animation anim = new AlphaAnimation(1, 1);

    anim.setDuration(2000);

    image.startAnimation(anim);
    anim.setAnimationListener(new AnimationListener() {
        public void onAnimationEnd(Animation animation) 
        {
            image.clearAnimation();
            image.invalidate();
            fadeout(image);

        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onAnimationStart(Animation animation) {
            // TODO Auto-generated method stub

        }
    });
}     
public void fadeout (final ImageView image)
{
    Animation anim = new AlphaAnimation(1,0);

    anim.setDuration(2000);

    image.startAnimation(anim);
    anim.setAnimationListener(new AnimationListener() {
        public void onAnimationEnd(Animation animation) 
        {
            image.clearAnimation();
            image.invalidate();
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onAnimationStart(Animation animation) {
            // TODO Auto-generated method stub

        }
    });
}    

以前の試みとこのことを正しく機能させるためのクリアアニメーションと無効化。必要かどうかはわかりません。

これが誰かを助けることを願っています。


ライアン


1

私はこれを手に入れました...私はビューを連続的に円を描くように回転させようとしていました。

以前はrotation.setRepeatMode(-1)を使用していましたが、機能しませんでした。setrepeatcountに切り替えて、動作します。これはジェリービーン4.2.2にあります

 ObjectAnimator rotation = ObjectAnimator.ofFloat(myview,
                          "rotation", 360).setDuration(2000);
                rotation.setRepeatMode(-1);
          rotation.setRepeatCount(Animation.INFINITE); 
 rotation.start();

0

私は同じ問題に直面しましたが、UIスレッドが非常にビジーになることがあるため、Javaでタイミング調整を行いたくありませんでした。inFINITEフラグはsetタグでは機能しません。だから私は小さなコードで問題を解決しました:

mAnimation = (AnimationSet) AnimationUtils.loadAnimation(myContext, R.anim.blink);
mIcon.startAnimation(mAnimation);
mAnimation.setAnimationListener(new AnimationListener() {
    public void onAnimationStart(Animation animation) {}
    public void onAnimationRepeat(Animation animation) {}
    public void onAnimationEnd(Animation animation) {
        mIcon.startAnimation(mAnimation);
    }
});

次のXMLを使用します。

<alpha
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromAlpha="0.0"
    android:toAlpha="1.0" />

<alpha
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromAlpha="0.9"
    android:startOffset="1000"
    android:toAlpha="0.0" />

mIconは私のレイアウトからのImageViewです。


0

私はこの問題を解決しました。これは私のバージョンの修正です:

public class HelloAndroidActivity extends Activity {
private static String TAG = "animTest";
private Animation scaleAnimation;
private int currentCover = 0;
private List<ImageView> imageViews = new ArrayList<ImageView>(3);
private Button btn;
private ImageView img;

/**
 * Called when the activity is first created.
 * @param savedInstanceState If the activity is being re-initialized after 
 * previously being shut down then this Bundle contains the data it most 
 * recently supplied in onSaveInstanceState(Bundle). <b>Note: Otherwise it is null.</b>
 */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.i(TAG, "onCreate");
    setContentView(R.layout.test);

    img = (ImageView)findViewById(R.id.testpict);
    imageViews.add(img);
    img = (ImageView)findViewById(R.id.testpictTwo);
    imageViews.add(img);
    img = (ImageView)findViewById(R.id.testpict3);
    imageViews.add(img);

    scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.photo_scale);
    scaleAnimation.setAnimationListener(new CyclicAnimationListener());

    btn = (Button)findViewById(R.id.startBtn);
    btn.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            imageViews.get(0).startAnimation(scaleAnimation);
        }
    });



}

private class CyclicAnimationListener implements AnimationListener{

    @Override
    public void onAnimationEnd(Animation animation) {
        currentCover += 1;
        if(currentCover >= imageViews.size()){
            currentCover = 0;
        }
        img = imageViews.get(currentCover);
        scaleAnimation = AnimationUtils.loadAnimation(HelloAndroidActivity.this, R.anim.photo_scale);
        scaleAnimation.setAnimationListener(new CyclicAnimationListener());
        img.startAnimation(scaleAnimation);
    }

    @Override
    public void onAnimationRepeat(Animation animation) {
        Log.d("Animation", "Repeat");
    }

    @Override
    public void onAnimationStart(Animation animation) {

    }

}

}

0

下位互換性のあるアプリで作業しているときに、この問題に遭遇しました。とてもイライラする!onCreateから呼び出すことができ、アニメーションリソースを無期限のループにキックオフする、優れた回避策クラスをコーディングすることになりました。

クラスAnimationLooperは、https//gist.github.com/2018678から入手できます。


0

インターネットからの回答を調べた後、私は自分にぴったりの解決策を見つけました。(はい、repeatCountとrepeatModeはanimationSetと一緒に使用すると非常にバグがあります)。

anim_rotate_fade.xml:

<?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:ordering="together" >

    <objectAnimator
        android:duration="3000"
        android:propertyName="rotation"
        android:repeatCount="1"
        android:valueTo="360"
        android:valueType="floatType" />

    <objectAnimator
        android:duration="3000"
        android:propertyName="alpha"
        android:repeatCount="1"
        android:repeatMode="reverse"
        android:valueFrom="0.0"
        android:valueTo="0.3"
        android:valueType="floatType" />

    <objectAnimator
        android:duration="3000"
        android:propertyName="y"
        android:repeatCount="1"
        android:repeatMode="reverse"
        android:valueFrom="380"
        android:valueTo="430"
        android:valueType="floatType" />

</set>

アクティビティ中:(アニメーションが終了した後にわずかな遅延を導入して解決します)。

ImageView starlightImageView = new ImageView(this);
starlightImageView.setImageResource(R.drawable.starlight);
final AnimatorSet animate = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.anim.anim_rotate_fade);
AnimatorListenerAdapter animatorListener = new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        new Handler().postDelayed(new Runnable() {
            @Override public void run() {
                animate.start();
            }
        }, 1000);
    }
};
animate.setTarget(starlightImageView);
animate.addListener(animatorListener);

研究したいクラスはたくさんありますが、現在は柔軟性の高いobjectAnimatorを使用しています。AnimationまたはAnimationUtilsの使用はお勧めしません。

  • アニメーション
  • AnimationUtils
  • アニメーター
  • AnimatorInflater
  • AnimatorListener
  • AnimatorListenerAdapter


0

@Danufrの回答を少し調整して、リソースが再度読み込まれないようにします。

    operator = (ImageView) findViewById(R.id.operator_loading);
  final  Animation ani = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.finding_operator);


    ani.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {

        }

        @Override
        public void onAnimationEnd(Animation animation) {

            operator.startAnimation(ani);

        }

        @Override
        public void onAnimationRepeat(Animation animation) {

        }
    });

    operator.setAnimation(ani);

0

私はスレッドを使用してこの問題を解決しました。

Button btn = (Button) findViewById(R.id.buttonpush);
    final TextView textview = (TextView) findViewById(R.id.hello);
    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            textview.setText("...................");
            final Animation animationtest = AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.slide_in_left);
            animationtest.setDuration(1000);

            final Handler handler = new Handler();
            Runnable runnable = new Runnable() {
                public void run() {
                    handler.postDelayed(this, 1500);
                    textview.startAnimation(animationtest);
                }
            };
            handler.postDelayed(runnable, 500); // start
            handler.removeCallbacks(runnable); //STOP Timer

        }
    });

0

正常に動作しています

 GifDrawable gifDrawable = (GifDrawable) gifImageView.getDrawable();
    gifDrawable.setLoopCount(0);

0

私の場合、上記の解決策はどれも機能しませんでした。Danuofrによるソリューションはアニメーションセットで機能しましたが、ユニットテストを行っていたとき、私のテストはこの無限ループでスタックしていました。最後に、私の場合に固有に、このアニメーションを特定の回数繰り返す必要がありました。そのため、アニメーションのコピーをanim_rot.xmlにカスケード方式で手動で追加し、オフセット値を追加しました。。私はそれが悪いことを知っていて、多くの人にとってはうまくいかないでしょうが、それが私の場合の唯一の回避策でした。

anim_rot.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <rotate
        android:duration="2000"
        android:fromDegrees="20"
        android:pivotX="29%"
        android:pivotY="50%"
        android:toDegrees="-20" />
    <rotate
        android:duration="2000"
        android:fromDegrees="-20"
        android:pivotX="29%"
        android:pivotY="53%"
        android:startOffset="2000"
        android:toDegrees="20" />
    <rotate
        android:startOffset="4000"
        android:duration="2000"
        android:fromDegrees="20"
        android:pivotX="29%"
        android:pivotY="56%"
        android:toDegrees="-20" />
    <rotate
        android:duration="2000"
        android:fromDegrees="-20"
        android:pivotX="29%"
        android:pivotY="59%"
        android:startOffset="6000"
        android:toDegrees="20" />
    <rotate
        android:startOffset="8000"
        android:duration="2000"
        android:fromDegrees="20"
        android:pivotX="29%"
        android:pivotY="62%"
        android:toDegrees="-20" />
    <rotate
        android:duration="2000"
        android:fromDegrees="-20"
        android:pivotX="29%"
        android:pivotY="65%"
        android:startOffset="10000"
        android:toDegrees="20" />
</set>

アニメーションを3回繰り返すためにこれを行いました。オフセット値を追加することにより、コピーを追加して特定の回数繰り返すことができます。


-1

ループしているスレッドまたはwhile / forステートメントにコードを追加してみてください


さて、私が見つけた唯一の解決策は、setタグの使用を避けることです。
Pavel Chernov 2010
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.