LoginSignup
0
1

More than 5 years have passed since last update.

StateListDrawable の中に AnimationDrawable が入っていても自動再生して欲しい

Posted at

独自のボタンを作るため、 ImageButtonbackgroundAnimationDrawable を指定することはよくあると思います。

「簡単な繰り返しアニメーションだから、WebページのGIFアニメみたく自動的に再生開始してくれたらいいのに!」

しかも

有効時と無効時では別のDrawableを表示する
StateListDrawable の中に AnimationDrawable を入れる)

button_background.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <!--無効時 (pngファイル1枚)-->  
    <item android:state_enabled="false" android:drawable="@drawable/button_disable" />

    <!--有効時(AnimationDrawable)-->
    <item android:drawable="@drawable/button_enable_animating" />
</selector>

なんてなったときにはどうしたらいいのでしょう。

結論

結論を先に。

ImageButton を継承したクラスを作ってどうにかしました。
適当に backgroundsrc にリソースを突っ込むと再生してくれます。

AnimationAutoStartImageButton.java
import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.widget.ImageButton;


public class AnimationAutoStartImageButton extends ImageButton {
    public AnimationAutoStartImageButton(Context context) {
        super(context);
    }

    public AnimationAutoStartImageButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AnimationAutoStartImageButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();

        startAnimationOfDrawable(getDrawable());
        startAnimationOfDrawable(getBackground());
    }

    private void startAnimationOfDrawable(@Nullable Drawable drawable) {
        if (drawable == null) {
            return;
        }
        Drawable surface = drawable.getCurrent();
        if (!(surface instanceof AnimationDrawable)) {
            return;
        }
        AnimationDrawable animDraw = (AnimationDrawable)surface;
        if (!animDraw.isRunning()) {
            animDraw.start();
        }
    }
}

結局、何が問題だったのか

いくつかあります。

  1. background に指定した AnimationDrawableAnimationDrawable#start() を叩かないとアニメーションが再生されない
  2. AnimationDrawable in StateListDrawable とかやると単純に start() 叩けない

background に指定した AnimationDrawableAnimationDrawable#start() を叩かないとアニメーションが再生されない

どうやら、 src に指定した AnimationDrawable は自動的に再生されるらしいのです。

参考:Animation-list (animationDrawable) autostart

が、srcに指定してしまうと、ボタンの柄を変更する事ができません。backgroundを使うしかない。

そうなると、コードからbackgroundのAnimationDrawableを取得して start() を叩くしかない…
なんて面倒なんだ!

AnimationDrawable in StateListDrawable とかやると単純に start() 叩けない

StateListDrawable#getCurrent() で現在のDrawableを取得して、それに対して start() を叩く、という面倒なことをしないといけません。

しかも、 getCurrent() でとれるDrawableがAnimationDrawableである保証はどこにもない!
いちいちインスタンスの型の確認が必要!
つらい!

まとめ

AnimationDrawableに自動再生のオプションとかがあれば、こんなややこしいことしなくて済んだのになぁ、という無い物ねだりでした。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1