Android RadioButton drawableTop drawableBottomが中央に表示され、アニメーション付き


import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.MotionEvent;

public class TabRadioButton extends android.support.v7.widget.AppCompatRadioButton {
    /**       ,     3/4 */
    private static final float DEFAULT_SCALE_RATE = 0.75f;
    /**           */
    private static final int DEFAULT_DURATION = 200;
    /**   drawable size -1,         */
    private static final int DEFAULT_DRAWABLE_SIZE = -1;

    private Drawable leftDrawable;
    private Drawable topDrawable;
    private Drawable rightDrawable;
    private Drawable bottomDrawable;
    /**   drawable    */
    private int      drawableSize;
    private int      drawablePadding;
    private String   text;
    private float    textHeight;
    private float    textWidth;

    /**          */
    private boolean  enableAnimation;
    /**          */
    private Animator pressedAnimator;
    /**          */
    private Animator releasedAnimator;
    private long     duration;
    private float    scaleRate;

    public TabRadioButton(Context context) {
        this(context, null);
    }

    public TabRadioButton(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TabRadioButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        parseAttrs(context, attrs);
        init();
    }

    private void parseAttrs(Context context, AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.TabRadioButton);
        drawableSize = array.getDimensionPixelSize(R.styleable.TabRadioButton_trb_drawable_size, DEFAULT_DRAWABLE_SIZE);
        scaleRate = array.getFloat(R.styleable.TabRadioButton_trb_scale_rate, DEFAULT_SCALE_RATE);
        duration = array.getInteger(R.styleable.TabRadioButton_trb_duration, DEFAULT_DURATION);
        enableAnimation = array.getBoolean(R.styleable.TabRadioButton_trb_enable_animation, false);
        drawableSize = drawableSize < 0
                ? -1
                : drawableSize;
        array.recycle();
    }

    private void init() {
        setClickable(true);
        setFocusable(true);
        setGravity(Gravity.CENTER);
        text = getText().toString();
        if (TextUtils.isEmpty(text)){
            setTextSize(0);
        }

        //     
        pressedAnimator = getAnimator(true);
        releasedAnimator = getAnimator(false);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        this.performClick();
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                //         
                if (enableAnimation && !pressedAnimator.isRunning()){
                    pressedAnimator.start();
                }
                break;
            case MotionEvent.ACTION_UP:
                //         
                if (enableAnimation && !releasedAnimator.isRunning()){
                    releasedAnimator.start();
                }
                break;
        }
        return super.onTouchEvent(event);
    }

    @Override
    public boolean performClick() {
        return super.performClick();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Drawable[] drawables = getCompoundDrawables();
        leftDrawable = drawables[0];
        topDrawable = drawables[1];
        rightDrawable = drawables[2];
        bottomDrawable = drawables[3];

        textWidth = getFontWidth(getPaint(), text);
        textHeight = getFontHeight(getPaint());

        drawablePadding = getCompoundDrawablePadding();

        int drawableWidth;
        int drawableHeight;
        //       
        if (leftDrawable != null && topDrawable == null && rightDrawable == null && bottomDrawable == null){
            drawableWidth = drawableSize < 0
                    ? leftDrawable.getIntrinsicWidth()
                    : drawableSize;
            drawableHeight = drawableSize < 0
                    ? leftDrawable.getIntrinsicHeight()
                    : drawableSize;
            int left = (int) ((this.getWidth() - drawableWidth - drawablePadding - textWidth) / 2);
            leftDrawable.setBounds(left, 0, left + drawableWidth, drawableHeight);
        }
        //       
        if (topDrawable != null && leftDrawable == null && rightDrawable == null && bottomDrawable == null){
            drawableWidth = drawableSize < 0
                    ? topDrawable.getIntrinsicWidth()
                    : drawableSize;
            drawableHeight = drawableSize < 0
                    ? topDrawable.getIntrinsicHeight()
                    : drawableSize;
            int top = (int) ((this.getHeight() - drawableHeight - drawablePadding - textHeight) / 2);
            topDrawable.setBounds(0, top, drawableWidth, top + drawableHeight);
        }
        //  drawable     
        setCompoundDrawables(leftDrawable, topDrawable, rightDrawable, bottomDrawable);
        super.onDraw(canvas);
    }

    /**
     * @param whenPressed          
     * @return
     */
    private Animator getAnimator(boolean whenPressed) {
        return getDefaultScaleAnimator(whenPressed ? 1.0f : scaleRate,
                whenPressed ? scaleRate : 1.0f, duration);
    }

    private Animator getDefaultScaleAnimator(float from, float to, long duration){
        AnimatorSet    animatorSet = new AnimatorSet();
        ObjectAnimator animatorX   = ObjectAnimator.ofFloat(this, "ScaleX", from, to);
        ObjectAnimator animatorY   = ObjectAnimator.ofFloat(this, "ScaleY", from, to);
        animatorSet.play(animatorX).with(animatorY);
        animatorSet.setDuration(duration);
        animatorSet.setTarget(this);
        return animatorSet;
    }

    private float getFontWidth(Paint paint, String text) {
        return paint.measureText(text);
    }

    private float getFontHeight(Paint paint){
        Paint.FontMetrics fm = paint.getFontMetrics();
        return fm.descent - fm.ascent;
    }

    public void setEnableAnimation(boolean enableAnimation) {
        this.enableAnimation = enableAnimation;
    }

    public void setDuration(long duration) {
        this.duration = duration;
    }

    public void setScaleRate(float scaleRate) {
        this.scaleRate = scaleRate;
    }
}