ProgressBar用にDrawableを作成メモ

基本的にはdrawの中で描画をしてあげるだけで良い
動きをつける場合にはgetLevel()で取得できる値を元に行うと簡単
getLevel()の値の範囲は[0, 10000]
サイズの変更はonBoundsChange(Rect)で受け取れる(drawの前に最初に呼ばれるが必ずそうなのかは要調査)

public class MyDrawable extends Drawable {
    private static final int INDICATOR_COUNT = 12;
    private static final int MAX_LEVEL = 10000;

    private RectF rectF = new RectF();
    private Paint p;

    private int centerX;
    private int centerY;
    private int width;
    private int height;


    public MyDrawable() {
        p = new Paint();
    }

    @Override public void draw(@NonNull Canvas canvas) {
        int duration = MAX_LEVEL / 4;

        int currentPos = ((getLevel() % duration) / (duration / INDICATOR_COUNT)) % INDICATOR_COUNT;

        for (int i = 0; i < INDICATOR_COUNT; i++) {
            // 先頭との差によって色を変える[0xaaaaa, 0xffffff]の範囲で
            int diff = ((currentPos + INDICATOR_COUNT) - i) % INDICATOR_COUNT;
            diff = Math.max(Math.min(diff, 0x4), 0x0);
            p.setColor((0xff000000 | (0x00111111 * (0xf - diff))));

            float r = 32 * width / 100f;
            canvas.drawRoundRect(rectF, r, r, p);
            canvas.rotate(360f / INDICATOR_COUNT, centerX, centerY);
        }
    }

    @Override public void setAlpha(int i) {

    }

    @Override public void setColorFilter(ColorFilter colorFilter) {

    }

    @Override protected void onBoundsChange(Rect bounds) {
        super.onBoundsChange(bounds);
        centerX = bounds.centerX();
        centerY = bounds.centerY();
        width = bounds.width();
        height = bounds.height();
        float scale = width / 100f;

        rectF.set(centerX + 24 * scale, centerY - 4 * scale, width - 2 * scale, centerY + 4 * scale);
    }

    @Override public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }
}

今回作ったものは以下のような表示をする(背景は別で灰色にしています)

f:id:scache:20161216102154g:plain:w100

setAlphasetColorFilterについては調べられてないので調べる必要がある
また、getLevelを使う以外にもアニメーションを行える方法があるようなので他の方法も調べたい