6389


現在`drawable-hdpi`、`drawable-xhdpi`、`drawable-
xxhdpi`フォルダにそれぞれサイズの異なる画像を置いています。そしてアニメーションを行うのですが、なぜか`xxhdpi`の端末のみアニメーションが動作し、`xhdpi`の端末は一枚画像が表示されるだけで、`hdpi`の端末に至っては画像すら表示されません。なぜなのでしょうか？下記にコードを記します。すみませんが、どなたか分かる方がいればよろしくお願いします。

MainActivity

[code]

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState); setContentView(R.layout.activity_animation);
    
            animationImageView = (ImageView)findViewById(R.id.animation_imageview);
            animationImageView.post(new Runnable() {
                @Override
                public void run() {
                    if (getIntent().getStringExtra("animType").equals("normal_animation")) {
                        AnimationConfig animationConfig = new AnimationConfig(activity, activity);
                        animationConfig.setAnimationData(animationImageView, 2000, 2000, 50);
                        animationConfig.setAnimationFrame(R.drawable.slot_01);
                        animationConfig.setAnimationFrame(R.drawable.slot_02);
                        animationConfig.setAnimationFrame(R.drawable.slot_03);
                        animationConfig.setAnimationFrame(R.drawable.slot_04);
                        animationConfig.setAnimationFrame(R.drawable.slot_05);
                        animationConfig.setAnimationFrame(R.drawable.slot_06);
                        animationConfig.setAnimationFrame(R.drawable.slot_07);
                        animationConfig.setAnimationFrame(R.drawable.slot_08);
                        animationConfig.setAnimationFrame(R.drawable.slot_09);
                        animationConfig.setAnimationFrame(R.drawable.slot_10);
                        animationConfig.setAnimationFrame(R.drawable.slot_11);
                        animationConfig.setAnimationFrame(R.drawable.slot_12);
                        animationConfig.setAnimationFrame(R.drawable.slot_13);
                        animationConfig.setAnimationFrame(R.drawable.slot_14);
                        animationConfig.setAnimationFrame(R.drawable.slot_15);
                        animationConfig.startAnimation();
                    }
                }
            });
        }
    
[/code]

AnimationConfig

[code]

    public class AnimationConfig {
        private Activity mActivity;
        private Context mContext;
        private int mDuration;
        private int mOffset;
        private int mEachImageShowTime;
        private AnimationSet mAnimationSet;
        private ImageView mAnimationImageView;
        private List<Drawable> mFrameList = new ArrayList<Drawable>();
    
        public AnimationConfig(Activity activity, Context context) {
            mActivity = activity;
            mContext = context;
        }
    
        public void setAnimationFrame(int image) {
            mFrameList.add(mContext.getResources().getDrawable(image));
        }
    
        public void setAnimationData(ImageView imageView, int duration, int offset, int eachImageShowTime) {
            mAnimationImageView = imageView;
            mDuration = duration;
            mOffset = offset;
            mEachImageShowTime = eachImageShowTime;
        }
    
        public void startAnimation() {
            setFrameAnimation(mAnimationImageView, mEachImageShowTime);
            mAnimationImageView.startAnimation(setFadeAnimation(mDuration, mOffset));
        }
    
        public AnimationSet setFadeAnimation(int duration, final int offset){
            AlphaAnimation fadeIn = new AlphaAnimation(0, 1);
            final AlphaAnimation fadeOut = new AlphaAnimation(1, 0);
            fadeIn.setDuration(duration);
    
            fadeIn.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                    fadeOut.setStartOffset(offset);
                }
    
                @Override
                public void onAnimationEnd(Animation animation) {
    
                }
    
                @Override
                public void onAnimationRepeat(Animation animation) {
    
                }
            });
    
            fadeOut.setDuration(duration);
            fadeOut.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
    
                }
    
                @Override
                public void onAnimationEnd(Animation animation) {
                    mAnimationImageView.setVisibility(View.GONE);
                    mAnimationSet.setFillAfter(true);
                    screenTransition();
                }
    
                @Override
                public void onAnimationRepeat(Animation animation) {
    
                }
            });
    
            mAnimationSet = new android.view.animation.AnimationSet(false); {
                mAnimationSet.addAnimation(fadeIn);
                mAnimationSet.addAnimation(fadeOut);
            }
    
            return mAnimationSet;
        }
    
        public void setFrameAnimation(ImageView imageView, int sec) {
            mAnimationImageView = imageView;
            AnimationDrawable anim = new AnimationDrawable();
            for (Drawable frame:mFrameList) {
                anim.addFrame(frame, sec);
            }
            anim.setOneShot(false);
            imageView.setImageDrawable(anim);
        }
    }
    
[/code]


CC BY-SA 3.0
2015-02-10T04:35:44.677
6229
2015-02-12T13:36:52.090
2015-02-10T06:16:24.630
5210
5210
question
android
端末によってアニメーションが動かない


表題に対する回答としては、`AnimationDrawable#start()`が呼び出されていない、になります。

では、なぜ端末によっては`AnimationDrawable`が自動的に再生されるのでしょう？これは端末密度による違いではなく、単に一部のバージョンのバグと思われます。

特定のバージョン以降、`setImageDrawable()`で渡された`Drawable`は、`Drawable#setVisible(true,
true)`が呼び出されるのようになったのですが、このとき`AnimationDrawable#setVisible()`が以下のような実装になっているバージョンでは自動再生されるのだと思います。

[code]

    @Override
    public boolean setVisible(boolean visible, boolean restart) {
        boolean changed = super.setVisible(visible, restart);
        if (visible) {
            if (changed || restart) {
                setFrame(0, true, true);
            }
        } else {
          unscheduleSelf(this);
        }
        return changed;
    }
    
[/code]

少なくともICEの頃までは`Drawable#setVisible(true, true)`が呼び出されなかったので、古過ぎると発生しません。

現在（5.0.1）の`setVisible()`は以下のような実装になっています。

[code]

    @Override
    public boolean setVisible(boolean visible, boolean restart) {
        final boolean changed = super.setVisible(visible, restart);
        if (visible) {
            if (restart || changed) {
                boolean startFromZero = restart || mCurFrame < 0 ||
                        mCurFrame >= mAnimationState.getChildCount();
                setFrame(startFromZero ? 0 : mCurFrame, true, mAnimating);
            }
        } else {
            unscheduleSelf(this);
        }
        return changed;
    }
    
[/code]

`setFrame()`の第三引数でアニメーションするかどうかが決まるのですが、`mAnimating`のフラグで管理することで、必ず`true`を渡してしまうバグを修正しています。


CC BY-SA 3.0
2015-02-12T13:31:18.503
6389
2015-02-12T13:36:52.090
2015-02-12T13:36:52.090
5337
5337
6229
answer