Android Open Source - Genius-Android Genius Check Box






From Project

Back to project page Genius-Android.

License

The source code is released under:

Apache License

If you think the Android project Genius-Android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2014 Qiujuer <qiujuer@live.cn>
 * WebSite http://www.qiujuer.net//  ww  w.ja v  a 2 s  .c o  m
 * Created 12/29/2014
 * Changed 01/14/2015
 * Version 2.0.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.qiujuer.genius.widget;

import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Property;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.Checkable;

import net.qiujuer.genius.Attributes;
import net.qiujuer.genius.R;

import static android.graphics.Paint.ANTI_ALIAS_FLAG;

/**
 * Created by Qiujuer
 * on 2014/12/29.
 */
public class GeniusCheckBox extends View implements Checkable, Attributes.AttributeChangeListener {
    private static final Interpolator ANIMATION_INTERPOLATOR = new DecelerateInterpolator();
    private static final ArgbEvaluator ARGB_EVALUATOR = new ArgbEvaluator();
    private static final int THUMB_ANIMATION_DURATION = 250;
    private static final int RING_WIDTH = 4;
    public static final int AUTO_CIRCLE_RADIUS = -1;

    // Animator
    private AnimatorSet mAnimatorSet;
    private float mSweepAngle;
    private int mCircleColor;

    private int mUnCheckedPaintColor = Attributes.DEFAULT_COLORS[4];
    private int mCheckedPaintColor = Attributes.DEFAULT_COLORS[2];

    private boolean mChecked;
    private boolean mIsAttachWindow;
    private boolean mBroadcasting;
    private OnCheckedChangeListener mOnCheckedChangeListener;

    private RectF mOval;
    private Paint mCirclePaint;
    private Paint mRingPaint;

    private float mCenterX, mCenterY;
    private boolean mCustomCircleRadius;
    private int mCircleRadius = AUTO_CIRCLE_RADIUS;
    private int mRingWidth = RING_WIDTH;

    private Attributes mAttributes;

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

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

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

    private void init(AttributeSet attrs, int defStyle) {
        // Load attributes
        if (mAttributes == null)
            mAttributes = new Attributes(this, getResources());

        boolean enable = isEnabled();
        boolean check = isChecked();

        if (attrs != null) {
            // Load attributes
            final TypedArray a = getContext().obtainStyledAttributes(
                    attrs, R.styleable.GeniusCheckBox, defStyle, 0);

            // getting common attributes
            int customTheme = a.getResourceId(R.styleable.GeniusCheckBox_g_theme, Attributes.DEFAULT_THEME);
            mAttributes.setThemeSilent(customTheme, getResources());

            // getting custom attributes
            mRingWidth = a.getDimensionPixelSize(R.styleable.GeniusCheckBox_g_ringWidth, mRingWidth);
            mCircleRadius = a.getDimensionPixelSize(R.styleable.GeniusCheckBox_g_circleRadius, mCircleRadius);
            mCustomCircleRadius = mCircleRadius != AUTO_CIRCLE_RADIUS;

            check = a.getBoolean(R.styleable.GeniusCheckBox_g_checked, false);
            enable = a.getBoolean(R.styleable.GeniusCheckBox_g_enabled, true);

            a.recycle();
        }
        // To check call performClick()
        setOnClickListener(null);

        // Refresh display with current params
        refreshDrawableState();

        // Init
        initPaint();
        initSize();
        initColor();

        // Init
        setEnabled(enable);
        setChecked(check);
    }

    private void initPaint() {
        if (mCirclePaint == null) {
            mCirclePaint = new Paint(ANTI_ALIAS_FLAG);
            mCirclePaint.setStyle(Paint.Style.FILL);
            mCirclePaint.setAntiAlias(true);
            mCirclePaint.setDither(true);
        }

        if (mRingPaint == null) {
            mRingPaint = new Paint();
            mRingPaint.setStrokeWidth(mRingWidth);
            mRingPaint.setStyle(Paint.Style.STROKE);
            mRingPaint.setStrokeJoin(Paint.Join.ROUND);
            mRingPaint.setStrokeCap(Paint.Cap.ROUND);
            mRingPaint.setAntiAlias(true);
            mRingPaint.setDither(true);
        }
    }

    private void initSize() {
        int paddingLeft = getPaddingLeft();
        int paddingTop = getPaddingTop();
        int paddingRight = getPaddingRight();
        int paddingBottom = getPaddingBottom();

        int contentWidth = getWidth() - paddingLeft - paddingRight;
        int contentHeight = getHeight() - paddingTop - paddingBottom;

        if (contentWidth > 0 && contentHeight > 0) {
            int center = Math.min(contentHeight, contentWidth) / 2;
            int areRadius = center - (mRingWidth + 1) / 2;
            mCenterX = center + paddingLeft;
            mCenterY = center + paddingTop;

            if (mOval == null)
                mOval = new RectF(mCenterX - areRadius, mCenterY - areRadius, mCenterX + areRadius, mCenterY + areRadius);
            else {
                mOval.set(mCenterX - areRadius, mCenterY - areRadius, mCenterX + areRadius, mCenterY + areRadius);
            }

            if (!mCustomCircleRadius)
                mCircleRadius = center - mRingWidth * 2;
            else if (mCircleRadius > center)
                mCircleRadius = center;

            // Refresh view
            if (!isInEditMode()) {
                invalidate();
            }
        }
    }

    private void initColor() {
        if (mAttributes == null)
            return;
        if (isEnabled()) {
            mUnCheckedPaintColor = mAttributes.getColor(4);
            mCheckedPaintColor = mAttributes.getColor(2);
        } else {
            mUnCheckedPaintColor = mAttributes.getColor(5);
            mCheckedPaintColor = mAttributes.getColor(3);
        }
        setCircleColor(isChecked() ? mCheckedPaintColor : mUnCheckedPaintColor);
    }

    private void setSweepAngle(float value) {
        mSweepAngle = value;
        invalidate();
    }

    private void setCircleColor(int color) {
        mCircleColor = color;
        invalidate();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // Init this Layout size
        initSize();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (isInEditMode()) {
            initSize();
        }

        mCirclePaint.setColor(mCircleColor);
        canvas.drawCircle(mCenterX, mCenterY, mCircleRadius, mCirclePaint);

        if (mOval != null) {
            mRingPaint.setColor(mUnCheckedPaintColor);
            canvas.drawArc(mOval, 225, 360, false, mRingPaint);
            mRingPaint.setColor(mCheckedPaintColor);
            canvas.drawArc(mOval, 225, mSweepAngle, false, mRingPaint);
        }
    }

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

    @Override
    public void setEnabled(boolean enabled) {
        if (enabled != isEnabled()) {
            super.setEnabled(enabled);
            initColor();
        }
    }

    @Override
    public boolean isChecked() {
        return mChecked;
    }

    @Override
    public void toggle() {
        setChecked(!mChecked);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        mIsAttachWindow = true;
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mIsAttachWindow = false;
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    @Override
    public void setChecked(boolean checked) {
        if (mChecked != checked) {
            mChecked = checked;
            refreshDrawableState();

            // To Animator
            if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && isAttachedToWindow() && isLaidOut())
                    || (mIsAttachWindow && mOval != null)) {
                animateThumbToCheckedState(checked);
            } else {
                // Immediately move the thumb to the new position.
                cancelPositionAnimator();
                setCircleColor(checked ? mCheckedPaintColor : mUnCheckedPaintColor);
                setSweepAngle(checked ? 360 : 0);
            }

            // Avoid infinite recursions if setChecked() is called from a listener
            if (mBroadcasting) {
                return;
            }
            mBroadcasting = true;
            if (mOnCheckedChangeListener != null) {
                mOnCheckedChangeListener.onCheckedChanged(this, checked);
            }
            mBroadcasting = false;
        }
    }

    @Override
    public void onThemeChange() {
        init(null, 0);
    }

    @Override
    public Attributes getAttributes() {
        return mAttributes;
    }

    public void setRingWidth(int width) {
        if (mRingWidth != width) {
            mRingWidth = width;
            mRingPaint.setStrokeWidth(mRingWidth);
            initSize();
        }
    }

    public void setCircleRadius(int radius) {
        if (mCircleRadius != radius) {
            if (radius < 0)
                mCustomCircleRadius = false;
            else {
                mCustomCircleRadius = true;
                mCircleRadius = radius;
            }
            initSize();
        }
    }

    public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
        mOnCheckedChangeListener = listener;
    }

    /**
     * =============================================================================================
     * The Animate
     * =============================================================================================
     */

    private void animateThumbToCheckedState(boolean newCheckedState) {
        ObjectAnimator sweepAngleAnimator = ObjectAnimator.ofFloat(this, SWEEP_ANGLE, newCheckedState ? 360 : 0);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
            sweepAngleAnimator.setAutoCancel(true);

        ObjectAnimator circleColorAnimator = newCheckedState ? ObjectAnimator.ofObject(this, CIRCLE_COLOR, ARGB_EVALUATOR, mUnCheckedPaintColor, mCheckedPaintColor) :
                ObjectAnimator.ofObject(this, CIRCLE_COLOR, ARGB_EVALUATOR, mCheckedPaintColor, mUnCheckedPaintColor);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
            circleColorAnimator.setAutoCancel(true);

        mAnimatorSet = new AnimatorSet();
        mAnimatorSet.playTogether(
                sweepAngleAnimator,
                circleColorAnimator
        );
        // set Time
        mAnimatorSet.setDuration(THUMB_ANIMATION_DURATION);
        mAnimatorSet.setInterpolator(ANIMATION_INTERPOLATOR);
        mAnimatorSet.start();
    }

    private void cancelPositionAnimator() {
        if (mAnimatorSet != null) {
            mAnimatorSet.cancel();
        }
    }

    /**
     * =============================================================================================
     * The custom properties
     * =============================================================================================
     */

    private static final Property<GeniusCheckBox, Float> SWEEP_ANGLE = new Property<GeniusCheckBox, Float>(Float.class, "sweepAngle") {
        @Override
        public Float get(GeniusCheckBox object) {
            return object.mSweepAngle;
        }

        @Override
        public void set(GeniusCheckBox object, Float value) {
            object.setSweepAngle(value);
        }
    };
    private static final Property<GeniusCheckBox, Integer> CIRCLE_COLOR = new Property<GeniusCheckBox, Integer>(Integer.class, "circleColor") {
        @Override
        public Integer get(GeniusCheckBox object) {
            return object.mCircleColor;
        }

        @Override
        public void set(GeniusCheckBox object, Integer value) {
            object.setCircleColor(value);
        }
    };

    /**
     * Interface definition for a callback to be invoked when the checked state
     * of a compound button changed.
     */
    public static interface OnCheckedChangeListener {
        /**
         * Called when the checked state of a compound button has changed.
         *
         * @param checkBox  The compound button view whose state has changed.
         * @param isChecked The new checked state of buttonView.
         */
        void onCheckedChanged(GeniusCheckBox checkBox, boolean isChecked);
    }
}




Java Source Code List

net.qiujuer.genius.ApplicationTest.java
net.qiujuer.genius.Attributes.java
net.qiujuer.genius.GeniusUI.java
net.qiujuer.genius.Genius.java
net.qiujuer.genius.animation.TouchEffectAnimator.java
net.qiujuer.genius.animation.TouchEffect.java
net.qiujuer.genius.app.BlurKit.java
net.qiujuer.genius.app.BlurNative.java
net.qiujuer.genius.app.UIKitHandlerPoster.java
net.qiujuer.genius.app.UIKitSyncPost.java
net.qiujuer.genius.app.UIKit.java
net.qiujuer.genius.command.CommandExecutor.java
net.qiujuer.genius.command.CommandService.java
net.qiujuer.genius.command.Command.java
net.qiujuer.genius.nettool.DnsResolve.java
net.qiujuer.genius.nettool.NetModel.java
net.qiujuer.genius.nettool.Ping.java
net.qiujuer.genius.nettool.Telnet.java
net.qiujuer.genius.nettool.TraceRouteContainer.java
net.qiujuer.genius.nettool.TraceRouteThread.java
net.qiujuer.genius.nettool.TraceRoute.java
net.qiujuer.genius.sample.ApplicationTest.java
net.qiujuer.genius.sample.CaseActivity.java
net.qiujuer.genius.sample.MainActivity.java
net.qiujuer.genius.sample.TwoActivity.java
net.qiujuer.genius.util.FixedList.java
net.qiujuer.genius.util.GeniusException.java
net.qiujuer.genius.util.HashUtils.java
net.qiujuer.genius.util.LogWriter.java
net.qiujuer.genius.util.Log.java
net.qiujuer.genius.util.Tools.java
net.qiujuer.genius.widget.GeniusButton.java
net.qiujuer.genius.widget.GeniusCheckBox.java
net.qiujuer.genius.widget.GeniusTextView.java