public class FreshDownloadView extends View {
private final String TAG = FreshDownloadView.class.getSimpleName();
//the circular radius
private float radius;
private int circular_color;
private int circular_progress_color;
private float circular_width;
private float circular_edge;
private Rect bounds;
private RectF mTempBounds;
private float mRealLeft;
private boolean mPrepareAniRun = false;
private float mRealTop;
private float mProgressTextSize;
private Rect textBounds;
private final String STR_PERCENT = "%";
private float mMarkOklength;
private AnimatorSet mOkAnimatorSet;
private AnimatorSet mErrorAnimatorSet;
private float mMarkArcAngle;
private float mMarkOkdegree;
private float mMarkOkstart;
private boolean mMarkOkAniRun;
private float mErrorPathLengthLeft;
private float mErrorPathLengthRight;
private float mErrorRightDegree;
private boolean mIfShowError;
private float mErrorLeftDegree;
private boolean mIfShowMarkRun = false;
private boolean mAttached;
private boolean mUsing;
private Path mDst = new Path();
/**
* the view's Status
*/
public enum STATUS implements Parcelable {
PREPARE, DOWNLOADING, DOWNLOADED, ERROR;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(ordinal());
}
public static final Creator<STATUS> CREATOR = new Creator<STATUS>() {
@Override
public STATUS createFromParcel(Parcel source) {
return STATUS.values()[source.readInt()];
}
@Override
public STATUS[] newArray(int size) {
return new STATUS[size];
}
};
}
//used when in downloaded
private enum STATUS_MARK {
DRAW_ARC, DRAW_MARK
}
private Paint publicPaint;
private Path path1;
private Path path2;
private Path path3;
private PathMeasure pathMeasure1;
private PathMeasure pathMeasure2;
private PathMeasure pathMeasure3;
private float mArrowStart;
private float startingArrow;
private float mArrow_left_length;
private float mArrow_right_length;
private float mArrow_center_length;
private DashPathEffect mArrow_center_effect;
private DashPathEffect mArrow_left_effect;
private DashPathEffect mArrow_right_effect;
private STATUS status = STATUS.PREPARE;
private STATUS_MARK status_mark;
private AnimatorSet prepareAnimator;
private float mProgress;
private final static float START_ANGLE = -90f;
private final static float TOTAL_ANGLE = 360f;
private final static float MARK_START_ANGLE = 65f;
private final static float DEGREE_END_ANGLE = 270f;
public FreshDownloadView(Context context) {
this(context, null);
}
public FreshDownloadView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public FreshDownloadView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
circular_edge = getResources().getDimension(R.dimen.edge);
bounds = new Rect();
mTempBounds = new RectF();
publicPaint = new Paint();
path1 = new Path();
path2 = new Path();
path3 = new Path();
pathMeasure1 = new PathMeasure();
pathMeasure2 = new PathMeasure();
pathMeasure3 = new PathMeasure();
textBounds = new Rect();
parseAttrs(context.obtainStyledAttributes(attrs, R.styleable.FreshDownloadView));
initPaint();
}
private void parseAttrs(TypedArray array) {
if (array != null) {
try {
setRadius(array.getDimension(R.styleable.FreshDownloadView_circular_radius, getResources().getDimension(R.dimen.default_radius)));
setCircularColor(array.getColor(R.styleable.FreshDownloadView_circular_color, getResources().getColor(R.color.default_circular_color)));
setProgressColor(array.getColor(R.styleable.FreshDownloadView_circular_progress_color, getResources().getColor(R.color.default_circular_progress_color)));
setCircularWidth(array.getDimension(R.styleable.FreshDownloadView_circular_width, getResources().getDimension(R.dimen.default_circular_width)));
setProgressTextSize(array.getDimension(R.styleable.FreshDownloadView_progress_text_size, getResources().getDimension(R.dimen.default_text_size)));
} finally {
array.recycle();
}
}
}
private void initPaint() {
publicPaint.setStrokeCap(Paint.Cap.ROUND);
publicPaint.setStrokeWidth(getCircularWidth());
publicPaint.setStyle(Paint.Style.STROKE);
publicPaint.setAntiAlias(true);
}
public void startDownload() {
mUsing = true;
if (prepareAnimator != null && mPrepareAniRun) {
return;
}
if (prepareAnimator == null) {
prepareAnimator = getPrepareAnimator();
}
prepareAnimator.start();
}
private AnimatorSet getPrepareAnimator() {
AnimatorSet animatorSet = new AnimatorSet();
ValueAnimator downAnimaor = ValueAnimator.ofFloat(0f, 0.3f, 0f).setDuration(500);
downAnimaor.setInterpolator(new DecelerateInterpolator());
downAnimaor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final float value = (float) animation.getAnimatedValue();
mArrowStart = startingArrow + (2 - .48f - 1f) * getRadius() * value;
updateArrow();
invalidate();
}
});
ValueAnimator upAnimator = ValueAnimator.ofFloat(0f, 1f).setDuration(800);
upAnimator.setInterpolator(new DecelerateInterpolator());
upAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final float value = (float) animation.getAnimatedValue();
mArrow_left_effect = new DashPathEffect(new float[]{mArrow_left_length, mArrow_left_length}, value * mArrow_left_length);
mArrow_right_effect = new DashPathEffect(new float[]{mArrow_right_length, mArrow_right_length}, value * mArrow_right_length);
float reduceDis = (1 - value) * (startingArrow - mRealTop);
path1.reset();
path1.moveTo(mRealLeft + radius, mRealTop + reduceDis);
path1.lineTo(mRealLeft + radius, mRealTop + reduceDis + mArrow_center_length);
mArrow_center_effect = new DashPathEffect(new float[]{mArrow_center_length, mArrow_center_length}, value * mArrow_center_length);
invalidate();
}
});
upAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mArrow_center_effect = null;
mArrow_right_effect = null;
mArrow_left_effect = null;
updateArrow();
}
@Override
public void onAnimationStart(Animator animation) {
}
});
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
status = STATUS.DOWNLOADING;
invalidate();
}
});
animatorSet.play(downAnimaor).before(upAnimator);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
mPrepareAniRun = false;
}
@Override
public void onAnimationStart(Animator animation) {
mPrepareAniRun = true;
}
@Override
public void onAnimationEnd(Animator animation) {
mPrepareAniRun = false;
}
});
return animatorSet;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int dx = 0;
int dy = 0;
dx += getPaddingLeft() + getPaddingRight() + getCurrentWidth();
dy += getPaddingTop() + getPaddingBottom() + getCurrentHeight();
final int measureWidth = resolveSizeAndState(dx, widthMeasureSpec, 0);
final int measureHeight = resolveSizeAndState(dy, heightMeasureSpec, 0);
setMeasuredDimension(Math.max(getSuggestedMinimumWidth(), measureWidth), Math.max(getSuggestedMinimumHeight(), measureHeight));
}
private int getCurrentHeight() {
return (int) ((getRadius() * 2) + circular_edge * 2);
}
private int getCurrentWidth() {
return (int) ((getRadius() * 2) + circular_edge * 2);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
final int top = 0 + getPaddingTop();
final int bottom = getHeight() - getPaddingBottom();
final int left = 0 + getPaddingLeft();
final int right = getWidth() - getPaddingRight();
updateBounds(top, bottom, left, right);
initArrowPath(top, bottom, left, right, getRadius());
}
private float buildAngle_percent_of_pain_width() {
final double perimeter = getRadius() * 2 * Math.PI;
final double width = getCircularWidth();
return (float) (width / perimeter);
}
/**
* update the Bounds of circular
*
* @param top
* @param bottom
* @param left
* @param right
*/
private void updateBounds(int top, int bottom, int left, int right) {
bounds.set(left, top, right, bottom);
}
private void initArrowPath(int top, int bottom, int left, int right, float radius) {
final float realTop = top + circular_edge;
mRealLeft = left + circular_edge;
mRealTop = realTop;
startingArrow = realTop + radius * .48f;
mArrowStart = startingArrow;
status = STATUS.PREPARE;
updateArrow();
}
/**
* update the Arrow's Status
*/
private void updateArrow() {
path1.reset();
path2.reset();
path3.reset();
path1.moveTo(mRealLeft + radius, mArrowStart);
path1.lineTo(mRealLeft + radius, mArrowStart + radius);
path2.moveTo(mRealLeft + radius, mArrowStart + radius);
path2.lineTo((float) (mRealLeft + radius - Math.tan(Math.toRadians(40)) * radius * 0.46f), mArrowStart + radius - radius * .46f);
path3.moveTo(mRealLeft + radius, mArrowStart + radius);
path3.lineTo((float) (mRealLeft + radius + Math.tan(Math.toRadians(40)) * radius * 0.46f), mArrowStart + radius - radius * .46f);
pathMeasure1.setPath(path1, false);
pathMeasure2.setPath(path2, false);
pathMeasure3.setPath(path3, false);
mArrow_center_length = pathMeasure1.getLength();
mArrow_left_length = pathMeasure2.getLength();
mArrow_right_length = pathMeasure3.getLength();
}
@Override
protected void onDraw(Canvas canvas) {
publicPaint.setPathEffect(null);
publicPaint.setStyle(Paint.Style.STROKE);
publicPaint.setColor(getCircularColor());
final RectF arcBounds = mTempBounds;
arcBounds.set(bounds);
arcBounds.inset(circular_edge, circular_edge);
canvas.drawArc(arcBounds, 0, 360, false, publicPaint);
switch (status) {
case PREPARE:
drawPrepare(canvas);
break;
case DOWNLOADING:
drawDownLoading(canvas, arcBounds);
break;
case DOWNLOADED:
drawDownLoaded(canvas, status_mark, arcBounds, mMarkArcAngle);
break;
case ERROR:
drawDownError(canvas);
break;
default:
}
}
/**
* Draw the Arrow
*/
private void drawPrepare(Canvas canvas) {
publicPaint.setColor(getProgressColor());
if (mArrow_center_effect != null) {
publicPaint.setPathEffect(mArrow_center_effect);
}
canvas.drawPath(path1, publicPaint);
if (mArrow_left_effect != null) {
publicPaint.setPathEffect(mArrow_left_effect);
}
canvas.drawPath(path2, publicPaint);
if (mArrow_right_effect != null) {
publicPaint.setPathEffect(mArrow_right_effect);
}
canvas.drawPath(path3, publicPaint);
}
/**
* Draw the Progress
*/
private void drawDownLoading(Canvas canvas, RectF arcBounds) {
final float progress_degree = mProgress;
publicPaint.setColor(getProgressColor());
if (progress_degree <= 0) {
canvas.drawPoint(mRealLeft + radius, mRealTop, publicPaint);
} else {
canvas.drawArc(arcBounds, START_ANGLE, (progress_degree) * TOTAL_ANGLE, false, publicPaint);
}
drawText(canvas, progress_degree);
}
private void drawText(Canvas canvas, float progress_degree) {
final String sDegree = String.valueOf(Math.round(progress_degree * 100));
final Rect rect = bounds;
publicPaint.setStyle(Paint.Style.FILL);
publicPaint.setTextSize(getProgressTextSize());
publicPaint.setTextAlign(Paint.Align.CENTER);
Paint.FontMetricsInt fontMetrics = publicPaint.getFontMetricsInt();
int baseline = (rect.bottom + rect.top - fontMetrics.bottom - fontMetrics.top) / 2;
canvas.drawText(sDegree, rect.centerX(), baseline, publicPaint);
publicPaint.getTextBounds(sDegree, 0, sDegree.length(), textBounds);
publicPaint.setTextSize(getProgressTextSize() / 3);
publicPaint.setTextAlign(Paint.Align.LEFT);
canvas.drawText(STR_PERCENT, rect.centerX() + textBounds.width() / 2 + .1f * radius, baseline, publicPaint);
}
/**
* Draw success
*/
private void drawDownLoaded(Canvas canvas, STATUS_MARK status, RectF bounds, float angle) {
publicPaint.setColor(getProgressColor());
switch (status) {
case DRAW_ARC:
canvas.drawArc(bounds, DEGREE_END_ANGLE - angle, 0.001f * TOTAL_ANGLE, false, publicPaint);
break;
case DRAW_MARK:
final Path dst = mDst;
dst.reset();
//to fix hardware speedup bug
dst.lineTo(0, 0);
pathMeasure1.getSegment(mMarkOkstart * mMarkOklength, (mMarkOkstart + mMarkOkdegree) * mMarkOklength, dst, true);
canvas.drawPath(dst, publicPaint);
break;
}
}
/**
* Draw error
*/
private void drawDownError(Canvas canvas) {
if (mIfShowMarkRun) {
final float progress = mProgress;
drawText(canvas, progress);
}
publicPaint.setColor(Color.WHITE);
final Path dst = mDst;
dst.reset();
//to fix hardware speedup bug
dst.lineTo(0, 0);
pathMeasure1.getSegment(0.2f * mErrorPathLengthLeft, mErrorRightDegree * mErrorPathLengthLeft, dst, true);
canvas.drawPath(dst, publicPaint);
dst.reset();
//to fix hardware speedup bug
dst.lineTo(0, 0);
pathMeasure2.getSegment(0.2f * mErrorPathLengthRight, mErrorLeftDegree * mErrorPathLengthRight, dst, true);
canvas.drawPath(dst, publicPaint);
}
/**
* update progress
*
* @param progress percent of 100,the value must from 0f to 1f
*/
public void updateProgress(float progress) {
setProgressInternal(progress);
}
/**
* update progress
*
* @param progress the value must from 0 to 100;
*/
public void updateProgress(int progress) {
updateProgress((float) progress / 100);
}
/**
* call it when you want to reset all;
*/
public void reset() {
resetStatus();
}
/**
* Called when you want to reset the Status.
* when @see #status==DOWNLOADING or animators are running,the call will be invalid.
*/
private void resetStatus() {
if (status == STATUS.DOWNLOADING || mPrepareAniRun || mIfShowError || mMarkOkAniRun) return;
status = STATUS.PREPARE;
mArrowStart = startingArrow;
updateArrow();
postInvalidate();
this.mProgress = 0;
mMarkOkdegree = 0f;
mMarkArcAngle = 0f;
mMarkOkstart = 0f;
mUsing = false;
mErrorLeftDegree = 0f;
mErrorRightDegree = 0f;
}
/**
* get Use Status
*
* @return if use by some task.
*/
public boolean using() {
return mUsing;
}
synchronized void setProgressInternal(float progressInternal) {
this.mProgress = progressInternal;
if (status == STATUS.PREPARE) {
startDownload();
}
invalidate();
if (progressInternal >= 1) {
showDownloadOk();
}
}
/**
* showDownLoadOK
*/
public void showDownloadOk() {
status = STATUS.DOWNLOADED;
makeOkPath();
if (mOkAnimatorSet != null && mMarkOkAniRun) {
return;
}
if (mOkAnimatorSet == null) {
mOkAnimatorSet = getDownloadOkAnimator();
}
mOkAnimatorSet.start();
}
/**
* make the Path to show
*/
private void makeOkPath() {
path1.reset();
int w2 = getMeasuredWidth() / 2;
int h2 = getMeasuredHeight() / 2;
double a = Math.cos(Math.toRadians(25)) * getRadius();
double c = Math.sin(Math.toRadians(25)) * getRadius();
double l = Math.cos(Math.toRadians(53)) * 2 * a;
double b = Math.sin(Math.toRadians(53)) * l;
double m = Math.cos(Math.toRadians(53)) * l;
path1.moveTo((float) (w2 - a), (float) (h2 - c));
path1.lineTo((float) (w2 - a + m), (float) (h2 - c + Math.sin(Math.toRadians(53)) * l));
path1.lineTo((float) (w2 + a), (float) (h2 - c));
pathMeasure1.setPath(path1, false);
mMarkOklength = pathMeasure1.getLength();
}
/**
* create a new DownLoadOkAnimator
*
* @return a new Animatorset for DownloadOk.
*/
private AnimatorSet getDownloadOkAnimator() {
AnimatorSet animatorSet = new AnimatorSet();
ValueAnimator roundAnimator = ValueAnimator.ofFloat(0f, MARK_START_ANGLE).setDuration(100);
roundAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mMarkArcAngle = (float) animation.getAnimatedValue();
invalidate();
}
});
roundAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
status_mark = STATUS_MARK.DRAW_ARC;
}
@Override
public void onAnimationEnd(Animator animation) {
status_mark = STATUS_MARK.DRAW_MARK;
}
});
ValueAnimator firstAnimator = ValueAnimator.ofFloat(0f, 0.7f).setDuration(200);
firstAnimator.setInterpolator(new AccelerateInterpolator());
firstAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mMarkOkdegree = (float) animation.getAnimatedValue();
invalidate();
}
});
ValueAnimator secondAnimator = ValueAnimator.ofFloat(0f, 0.35f, 0.2f).setDuration(500);
secondAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mMarkOkstart = (float) animation.getAnimatedValue();
invalidate();
}
});
secondAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
mIfShowMarkRun = false;
}
@Override
public void onAnimationEnd(Animator animation) {
mIfShowMarkRun = false;
}
@Override
public void onAnimationStart(Animator animation) {
mIfShowMarkRun = true;
}
});
animatorSet.play(firstAnimator).after(roundAnimator);
animatorSet.play(secondAnimator).after(200);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mMarkOkAniRun = true;
}
@Override
public void onAnimationEnd(Animator animation) {
mMarkOkAniRun = false;
}
@Override
public void onAnimationCancel(Animator animation) {
mMarkOkAniRun = false;
}
});
return animatorSet;
}
public void showDownloadError() {
status = STATUS.ERROR;
makeErrorPath();
invalidate();
if (mErrorAnimatorSet != null && mIfShowError) {
return;
}
if (mErrorAnimatorSet == null) {
mErrorAnimatorSet = getDownLoadErrorAnimator();
}
mErrorAnimatorSet.start();
}
private void makeErrorPath() {
final Rect bounds = this.bounds;
final int w2 = bounds.centerX();
final int h2 = bounds.centerY();
path1.reset();
path1.moveTo((float) (w2 - Math.cos(Math.toRadians(45)) * getRadius()), (float) (h2 - Math.sin(Math.toRadians(45)) * getRadius()));
path1.lineTo((float) (w2 + Math.cos(Math.toRadians(45)) * getRadius()), (float) (h2 + Math.sin(Math.toRadians(45)) * getRadius()));
pathMeasure1.setPath(path1, false);
mErrorPathLengthLeft = pathMeasure1.getLength();
path1.reset();
path1.moveTo((float) (w2 + Math.cos(Math.toRadians(45)) * getRadius()), (float) (h2 - Math.sin(Math.toRadians(45)) * getRadius()));
path1.lineTo((float) (w2 - Math.cos(Math.toRadians(45)) * getRadius()), (float) (h2 + Math.sin(Math.toRadians(45)) * getRadius()));
pathMeasure2.setPath(path1, false);
mErrorPathLengthRight = pathMeasure2.getLength();
}
private AnimatorSet getDownLoadErrorAnimator() {
final AnimatorSet errorSet = new AnimatorSet();
ValueAnimator animator1 = ValueAnimator.ofFloat(0.2f, 0.8f).setDuration(300);
animator1.setInterpolator(new OvershootInterpolator());
animator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
mErrorLeftDegree = value;
invalidate();
}
});
ValueAnimator animator2 = ValueAnimator.ofFloat(0.2f, 0.8f).setDuration(300);
animator2.setInterpolator(new OvershootInterpolator());
animator2.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mErrorRightDegree = (float) animation.getAnimatedValue();
invalidate();
}
});
errorSet.play(animator1);
errorSet.play(animator2).after(100);
errorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
mIfShowError = false;
}
@Override
public void onAnimationEnd(Animator animation) {
mIfShowError = false;
}
@Override
public void onAnimationStart(Animator animation) {
mIfShowError = true;
}
});
return errorSet;
}
public float getProgressTextSize() {
return mProgressTextSize;
}
public void setProgressTextSize(float mProgressTextSize) {
this.mProgressTextSize = mProgressTextSize;
}
public float getRadius() {
return radius;
}
public void setRadius(float radius) {
this.radius = radius;
}
public int getCircularColor() {
return circular_color;
}
public void setCircularColor(int circular_color) {
this.circular_color = circular_color;
}
public int getProgressColor() {
return circular_progress_color;
}
public void setProgressColor(int circular_progress_color) {
this.circular_progress_color = circular_progress_color;
}
public float getCircularWidth() {
return circular_width;
}
public void setCircularWidth(float circular_width) {
this.circular_width = circular_width;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mAttached = true;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mAttached = false;
}
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
FreshDownloadStatus fds = new FreshDownloadStatus(superState);
fds.circular_color = this.circular_color;
fds.circular_progress_color = this.circular_progress_color;
fds.circular_width = this.circular_width;
fds.progress = this.mProgress;
fds.radius = this.radius;
fds.status = this.status;
fds.mProgressTextSize = this.mProgressTextSize;
return fds;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
super.onRestoreInstanceState(state);
if (!(state instanceof FreshDownloadStatus)) {
return;
}
FreshDownloadStatus fds = (FreshDownloadStatus) state;
this.circular_color = fds.circular_color;
this.circular_progress_color = fds.circular_progress_color;
this.circular_width = fds.circular_width;
this.mProgress = fds.progress;
this.radius = fds.radius;
this.status = fds.status;
this.mProgressTextSize = fds.mProgressTextSize;
}
static class FreshDownloadStatus extends AbsSavedState {
public STATUS status;
public float progress;
public float radius;
public int circular_color;
public int circular_progress_color;
public float circular_width;
public float mProgressTextSize;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeFloat(this.progress);
dest.writeFloat(this.radius);
dest.writeInt(this.circular_color);
dest.writeInt(this.circular_progress_color);
dest.writeFloat(this.circular_width);
dest.writeFloat(this.mProgressTextSize);
Bundle bundle = new Bundle();
bundle.putParcelable("status", this.status);
dest.writeBundle(bundle);
}
public FreshDownloadStatus(Parcelable superState) {
super(superState);
}
protected FreshDownloadStatus(Parcel in) {
super(in);
in.readParcelable(FreshDownloadStatus.class.getClassLoader());
this.progress = in.readFloat();
this.radius = in.readFloat();
this.circular_color = in.readInt();
this.circular_progress_color = in.readInt();
this.circular_width = in.readFloat();
this.mProgressTextSize = in.readFloat();
}
protected FreshDownloadStatus(Parcel in, STATUS status) {
this(in);
this.status = status;
}
public static final Creator<FreshDownloadStatus> CREATOR = new Creator<FreshDownloadStatus>() {
@Override
public FreshDownloadStatus createFromParcel(Parcel source) {
Bundle bundle = source.readBundle(FreshDownloadStatus.class.getClassLoader());
bundle.setClassLoader(STATUS.class.getClassLoader());
bundle.getParcelable("status");
// STATUS status = source.readParcelable(STATUS.class.getClassLoader());
return new FreshDownloadStatus(source);
}
@Override
public FreshDownloadStatus[] newArray(int size) {
return new FreshDownloadStatus[size];
}
};
}
}