Skip to content

Instantly share code, notes, and snippets.

@cesco89
Last active February 9, 2023 05:09

Revisions

  1. cesco89 revised this gist Feb 21, 2014. 1 changed file with 7 additions and 0 deletions.
    7 changes: 7 additions & 0 deletions checkbox_selector_light.xml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/btn_radio_on_pressed_holo_light" android:state_checked="true"/>
    <item android:drawable="@drawable/btn_radio_off_pressed_holo_light" android:state_checked="false"/>

    </selector>
  2. cesco89 created this gist Feb 21, 2014.
    145 changes: 145 additions & 0 deletions CircleAnimatedCheckBox.java
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,145 @@
    import android.animation.ObjectAnimator;
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.util.AttributeSet;
    import android.util.TypedValue;
    import android.widget.CheckBox;
    import android.widget.ImageView;

    public class CircleAnimatedCheckBox extends CheckBox {

    private static final int PRESSED_COLOR_LIGHTUP = 255 / 25;
    private static final int PRESSED_RING_ALPHA = 75;
    private static final int DEFAULT_PRESSED_RING_WIDTH_DIP = 4;
    private static final int ANIMATION_TIME_ID = android.R.integer.config_shortAnimTime;

    private int centerY;
    private int centerX;
    private int outerRadius;
    private int pressedRingRadius;

    private Paint circlePaint;
    private Paint focusPaint;

    private float animationProgress;

    private int pressedRingWidth;
    private int defaultColor = Color.BLACK;
    private int pressedColor;
    private ObjectAnimator pressedAnimator;

    public CircleAnimatedCheckBox(Context context) {
    super(context);
    init(context, null);
    }

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

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

    @Override
    public void setPressed(boolean pressed) {
    super.setPressed(pressed);

    if (circlePaint != null) {
    circlePaint.setColor(pressed ? pressedColor : defaultColor);
    }

    if (pressed) {
    showPressedRing();
    } else {
    hidePressedRing();
    }
    }

    @Override
    protected void onDraw(Canvas canvas) {
    canvas.drawCircle(centerX, centerY, pressedRingRadius + animationProgress, focusPaint);
    //canvas.drawCircle(centerX, centerY, outerRadius - pressedRingWidth, circlePaint);
    super.onDraw(canvas);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    centerX = w/2;
    centerY = h/2;
    outerRadius = Math.min(w, h) / 2;
    pressedRingRadius = outerRadius - pressedRingWidth - pressedRingWidth / 2;
    }

    public float getAnimationProgress() {
    return animationProgress;
    }

    public void setAnimationProgress(float animationProgress) {
    this.animationProgress = animationProgress;
    this.invalidate();
    }

    public void setColor(int color) {
    this.defaultColor = color;
    this.pressedColor = getHighlightColor(color, PRESSED_COLOR_LIGHTUP);

    circlePaint.setColor(defaultColor);
    circlePaint.setAlpha(PRESSED_RING_ALPHA);
    focusPaint.setColor(defaultColor);
    //focusPaint.setAlpha(PRESSED_RING_ALPHA);

    this.invalidate();
    }

    private void hidePressedRing() {
    pressedAnimator.setFloatValues(pressedRingWidth, 0f);
    pressedAnimator.start();
    }

    private void showPressedRing() {
    pressedAnimator.setFloatValues(animationProgress, pressedRingWidth);
    pressedAnimator.start();
    }

    private void init(Context context, AttributeSet attrs) {
    //this.setFocusable(true);
    //this.setScaleType(ScaleType.CENTER_INSIDE);
    //setClickable(true);

    circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    circlePaint.setStyle(Paint.Style.FILL);

    focusPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    focusPaint.setStyle(Paint.Style.STROKE);

    pressedRingWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_PRESSED_RING_WIDTH_DIP, getResources()
    .getDisplayMetrics());

    int color = Color.BLACK;
    if (attrs != null) {
    final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleAnimatedCheckBox);
    color = a.getColor(R.styleable.CircleAnimatedCheckBox_cb_color, color);
    pressedRingWidth = (int) a.getDimension(R.styleable.CircleAnimatedCheckBox_cb_pressed_ring_width, pressedRingWidth);
    a.recycle();
    }

    setColor(color);

    focusPaint.setStrokeWidth(pressedRingWidth);
    final int pressedAnimationTime = getResources().getInteger(ANIMATION_TIME_ID);
    pressedAnimator = ObjectAnimator.ofFloat(this, "animationProgress", 0f, 0f);
    pressedAnimator.setDuration(pressedAnimationTime);
    }

    private int getHighlightColor(int color, int amount) {
    return Color.argb(Math.min(255, Color.alpha(color)), Math.min(255, Color.red(color) + amount),
    Math.min(255, Color.green(color) + amount), Math.min(255, Color.blue(color) + amount));
    }
    }
    7 changes: 7 additions & 0 deletions attrs.xml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    <declare-styleable name="CircleAnimatedCheckBox">
    <attr name="cb_color" format="color" />
    <attr name="cb_pressed_ring_width" format="dimension" />
    </declare-styleable>
    </resources>
    25 changes: 25 additions & 0 deletions example.xml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,25 @@
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?android:attr/selectableItemBackground"
    android:gravity="center_vertical"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:paddingRight="?android:attr/scrollbarSize" >


    <com.example.package.CircleAnimatedCheckBox
    android:id="@+id/cb"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:button="@drawable/checkbox_selector_light"
    android:focusable="false"
    android:scaleX="1.20"
    android:scaleY="1.20"
    app:cb_color="#CC33b5e5"
    app:cb_pressed_ring_width="2dp"/>

    </LinearLayout>