package com.dd.xda;
import com.dd.circular.progress.button.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.widget.ImageButton;
public class CircularProgressButton extends ImageButton {
public static final int IDLE_STATE_PROGRESS = 0;
private CircularAnimatedDrawable mAnimatedDrawable;
private StateManager mStateManager;
private State mState;
private int mColorIndicator;
private int mStrokeWidth;
private int mPaddingProgress;
private float mProgress;
private boolean mMorphingInProgress;
private int mDefaultSource;
public CircularProgressButton(Context context) {
super(context);
init(context, null);
}
public CircularProgressButton(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public CircularProgressButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
protected static TypedArray getTypedArray(Context context, AttributeSet attributeSet,
int[] attr) {
return context.obtainStyledAttributes(attributeSet, attr, 0, 0);
}
private void init(Context context, AttributeSet attributeSet) {
mStrokeWidth = (int) getContext().getResources().getDimension(R.dimen.cpb_stroke_width);
initAttributes(context, attributeSet);
mState = State.IDLE;
mStateManager = new StateManager(this);
}
private void initAttributes(Context context, AttributeSet attributeSet) {
TypedArray attr = getTypedArray(context, attributeSet, R.styleable.CircularProgressButton);
if (attr == null) {
return;
}
try {
mPaddingProgress = attr.getDimensionPixelSize(R.styleable
.CircularProgressButton_cpb_paddingProgress, 0);
int blue = getColor(R.color.cpb_blue);
mColorIndicator = attr.getColor(R.styleable
.CircularProgressButton_cpb_colorIndicator, blue);
} finally {
attr.recycle();
}
}
protected int getColor(int id) {
return getResources().getColor(id);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mProgress > 0 && mState == State.PROGRESS && !mMorphingInProgress) {
drawIndeterminateProgress(canvas);
}
}
private void drawIndeterminateProgress(Canvas canvas) {
if (mAnimatedDrawable == null) {
int offset = (getWidth() - getHeight()) / 2;
mAnimatedDrawable = new CircularAnimatedDrawable(mColorIndicator, mStrokeWidth);
int left = offset + mPaddingProgress;
int right = getWidth() - offset - mPaddingProgress;
int bottom = getHeight() - mPaddingProgress;
int top = mPaddingProgress;
mAnimatedDrawable.setBounds(left, top, right, bottom);
mAnimatedDrawable.setCallback(this);
mAnimatedDrawable.start();
} else {
mAnimatedDrawable.draw(canvas);
}
}
@Override
protected boolean verifyDrawable(Drawable who) {
return who == mAnimatedDrawable || super.verifyDrawable(who);
}
private void morphToProgress() {
removeIcon();
mMorphingInProgress = false;
mState = State.PROGRESS;
mStateManager.checkState(CircularProgressButton.this);
}
private void morphProgressToIdle() {
setImageResource(mDefaultSource);
mMorphingInProgress = false;
mState = State.IDLE;
mStateManager.checkState(CircularProgressButton.this);
}
protected void removeIcon() {
setImageDrawable(null);
}
public float getProgress() {
return mProgress;
}
public void setProgress(float progress) {
mProgress = progress;
if (mMorphingInProgress || getWidth() == 0) {
return;
}
mStateManager.saveProgress(this);
if (mProgress > IDLE_STATE_PROGRESS) {
if (mState == State.IDLE) {
morphToProgress();
} else if (mState == State.PROGRESS) {
invalidate();
}
} else if (mProgress == IDLE_STATE_PROGRESS) {
if (mState == State.PROGRESS) {
morphProgressToIdle();
}
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
setProgress(mProgress);
}
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState savedState = new SavedState(superState);
savedState.mProgress = mProgress;
return savedState;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
if (state instanceof SavedState) {
SavedState savedState = (SavedState) state;
mProgress = savedState.mProgress;
super.onRestoreInstanceState(savedState.getSuperState());
setProgress(mProgress);
} else {
super.onRestoreInstanceState(state);
}
}
@Override
public void setImageResource(final int defaultBackground) {
mDefaultSource = defaultBackground;
if (mState == State.IDLE) {
super.setImageResource(mDefaultSource);
}
}
private enum State {
PROGRESS, IDLE
}
static class SavedState extends BaseSavedState {
public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
private float mProgress;
public SavedState(Parcelable parcel) {
super(parcel);
}
private SavedState(Parcel in) {
super(in);
mProgress = in.readInt();
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeFloat(mProgress);
}
}
}