照例:效果图
具体实现
布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/aat_blue" android:orientation="vertical"> <RelativeLayout android:layout_width="200dp" android:layout_height="200dp" android:layout_gravity="center_horizontal"> <ImageView android:id="@+id/imageview" android:layout_width="200dp" android:layout_height="200dp" android:background="@drawable/score" /> <com.github.premnirmal.textcounter.CounterView android:id="@+id/value_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:layout_marginBottom="20dp" android:layout_marginTop="90dp" android:text="0" android:textColor="#ffffff" android:textSize="80sp" /> </RelativeLayout> <Button android:id="@+id/tv_change_value" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="20dp" android:text="改变数值" /> </LinearLayout>
ImageView 的background 是个蓝色背景图片
com.github.premnirmal.textcounter.CounterView 这个类 从github找的,可以自行search
我这里是在fragment中的。大家自己随意
/** * 描述: * 作者:Marc on 2016/7/22 10:03 * 邮箱:aliali_ha@yeah.net */ public class FragmentThree extends BaseFragment { ImageView imageView; CounterView valueTv; Button btn; CircularProgressDrawable drawable; Animator currentAnimation; @Override public void fetchData() { getmLoadingPager().loadData(); } @Override protected View initSuccess() { View view = View.inflate(UIUtils.getContext(), R.layout.test_drawable, null); imageView = (ImageView) view.findViewById(R.id.imageview); valueTv = (CounterView) view.findViewById(R.id.value_tv); view.findViewById(R.id.tv_change_value).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Random random = new Random(); int score = random.nextInt(150); valueTv.setStartValue(0); valueTv.setEndValue(score); valueTv.setIncrement(1); valueTv.start(); startRingAnim(score); } }); initViews(); return view; } private void initViews() { drawable = new CircularProgressDrawable.Builder() .setRingWidth(ScreenUtils.dip2px(UIUtils.getContext(),10)) .setRingWidth(ScreenUtils.dip2px(UIUtils.getContext(),9)) .setOutlineColor( getResources().getColor(android.R.color.transparent)) .setRingColor(getResources().getColor(android.R.color.white))//外圈白色 .setCenterColor( getResources().getColor(android.R.color.transparent)) .create(); imageView.setImageDrawable(drawable); Typeface tf = Typeface.createFromAsset(getActivity().getAssets(), "Uni_Sans_Light.otf"); valueTv.setTypeface(tf); valueTv.setAutoFormat(false); valueTv.setFormatter(new Formatter() { @Override public String format(String prefix, String suffix, float value) { return prefix + NumberFormat.getNumberInstance(Locale.US).format( value) + suffix; } }); valueTv.setAutoStart(false); } @Override protected LoadingPager.LoadResult initData() { SystemClock.sleep(2000); return LoadingPager.LoadResult.SUCCESS; } /** * 开始圆圈动画 * * @param score */ private void startRingAnim(int score) { currentAnimation = prepareStyle2Animation(score); currentAnimation.start(); } /** * 圆框动画 * * @param duration * @return */ private Animator prepareStyle2Animation(long duration) { AnimatorSet animation = new AnimatorSet(); float progress = (duration / 150f) * 0.727f; ObjectAnimator progressAnimation = ObjectAnimator.ofFloat(drawable, CircularProgressDrawable.PROGRESS_PROPERTY, 0.f, -progress); progressAnimation.setDuration(duration * 20); progressAnimation .setInterpolator(new AccelerateDecelerateInterpolator()); animation.play(progressAnimation); return animation; } }
这个类是我自己写的子类。取消fragment预加载。然后增加getLoading加载状态
CircularProgressDrawable 的代码如下
public class CircularProgressDrawable extends Drawable {
/**
* Factor to convert the factor to paint the arc.
* <p/>
* In this way the developer can use a more user-friendly [0..1f] progress
*/
public static final int PROGRESS_FACTOR = -360;
/**
* Property Inner Circle Scale.
* <p/>
* The inner ring is supposed to defaults stay 3/4 radius off the outer ring at (75% scale), but this
* property can make it grow or shrink via this equation: OuterRadius * Scale.
* <p/>
* A 100% scale will make the inner circle to be the same radius as the outer ring.
*/
public static final String CIRCLE_SCALE_PROPERTY = "circleScale";
/**
* Property Progress of the outer circle.
* <p/>
* The progress of the circle. If {@link #setIndeterminate(boolean) indeterminate flag} is set
* to FALSE, this property will be used to indicate the completion of the outer circle [0..1f].
* <p/>
* If set to TRUE, the drawable will activate the loading mode, where the drawable will
* show a 90º arc which will be spinning around the outer circle as much as progress goes.
*/
public static final String PROGRESS_PROPERTY = "progress";
/**
* Property Ring color.
* <p/>
* Changes the ring filling color
*/
public static final String RING_COLOR_PROPERTY = "ringColor";
/**
* Property circle color.
* <p/>
* Changes the inner circle color
*/
public static final String CIRCLE_COLOR_PROPERTY = "centerColor";
/**
* Property outline color.
* <p/>
* Changes the outline of the ring color.
*/
public static final String OUTLINE_COLOR_PROPERTY = "outlineColor";
/**
* Logger Tag for Logging purposes.
*/
public static final String TAG = "CircularProgressDrawable";
/**
* Paint object to draw the element.
*/
private final Paint paint;
/**
* Ring progress.
*/
protected float progress;
/**
* Color for the empty outer ring.
*/
protected int outlineColor;
/**
* Color for the completed ring.
*/
protected int ringColor;
/**
* Color for the inner circle.
*/
protected int centerColor;
/**
* Rectangle where the filling ring will be drawn into.
*/
protected final RectF arcElements;
/**
* Width of the filling ring.
*/
protected final int ringWidth;
/**
* Scale of the inner circle. It will affect the inner circle size on this equation:
* ([Biggest length of the Drawable] / 2) - (ringWidth / 2) * scale.
*/
protected float circleScale;
/**
* Set if it is an indeterminate
*/
protected boolean indeterminate;
/**
* Creates a new CouponDrawable.
*
* @param ringWidth Width of the filled ring
* @param circleScale Scale difference between the outer ring and the inner circle
* @param outlineColor Color for the outline color
* @param ringColor Color for the filled ring
* @param centerColor Color for the center element
*/
CircularProgressDrawable(int ringWidth, float circleScale, int outlineColor, int ringColor, int centerColor) {
this.progress = 0;
this.outlineColor = outlineColor;
this.ringColor = ringColor;
this.centerColor = centerColor;
this.paint = new Paint();
this.paint.setAntiAlias(true);
this.ringWidth = ringWidth;
this.arcElements = new RectF();
this.circleScale = circleScale;
this.indeterminate = false;
}
@Override
public void draw(Canvas canvas) {
final Rect bounds = getBounds();
// Calculations on the different components sizes
int size = Math.min(bounds.height(), bounds.width());
float outerRadius = (size / 2) - (ringWidth / 2);
float innerRadius = outerRadius * circleScale;
float offsetX = (bounds.width() - outerRadius * 2) / 2;
float offsetY = (bounds.height() - outerRadius * 2) / 2;
// Outline Circle
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(1);
paint.setColor(outlineColor);
canvas.drawCircle(bounds.centerX(), bounds.centerY(), outerRadius, paint);
// Inner circle
paint.setStyle(Paint.Style.FILL);
paint.setColor(centerColor);
canvas.drawCircle(bounds.centerX(), bounds.centerY(), innerRadius, paint);
int halfRingWidth = ringWidth / 2;
float arcX0 = offsetX + halfRingWidth;
float arcY0 = offsetY + halfRingWidth;
float arcX = offsetX + outerRadius * 2 - halfRingWidth;
float arcY = offsetY + outerRadius * 2 - halfRingWidth;
// Outer Circle
paint.setColor(ringColor);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(ringWidth);
paint.setStrokeCap(Paint.Cap.ROUND);
arcElements.set(arcX0 - 7, arcY0 - 7, arcX + 7, arcY + 7);
if (indeterminate) {
canvas.drawArc(arcElements, progress, 50, false, paint);
} else {
canvas.drawArc(arcElements, 139, progress, false, paint);
}
}
@Override
public void setAlpha(int alpha) {
paint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter cf) {
paint.setColorFilter(cf);
}
@Override
public int getOpacity() {
return 1 - paint.getAlpha();
}
/**
* Returns the progress of the outer ring.
* <p/>
* Will output a correct value only when the indeterminate mode is set to FALSE.
*
* @return Progress of the outer ring.
*/
public float getProgress() {
return progress / PROGRESS_FACTOR;
}
/**
* Sets the progress [0..1f]
*
* @param progress Sets the progress
*/
public void setProgress(float progress) {
if (indeterminate) {
this.progress = progress;
} else {
this.progress = PROGRESS_FACTOR * progress;
}
invalidateSelf();
}
/**
* Returns the inner circle scale.
*
* @return Inner circle scale in float multiplier.
*/
public float getCircleScale() {
return circleScale;
}
/**
* Sets the inner circle scale.
*
* @param circleScale Inner circle scale.
*/
public void setCircleScale(float circleScale) {
this.circleScale = circleScale;
invalidateSelf();
}
/**
* Get the indeterminate status of the Drawable
*
* @return TRUE if the Drawable is in indeterminate mode or FALSE if it is in progress mode.
*/
public boolean isIndeterminate() {
return indeterminate;
}
/**
* Sets the indeterminate parameter.
* <p/>
* The indeterminate parameter will change the behavior of the Drawable. If the indeterminate
* mode is set to FALSE, the outer ring will be able to be filled by using {@link #setProgress(float) setProgress}.
* <p/>
* Otherwise the drawable will enter "loading mode" and a 90º arc will be able to be spinned around
* the inner circle.
* <p/>
* <b>By default, indeterminate mode is set to FALSE.</b>
*
* @param indeterminate TRUE to activate loading mode. FALSE to activate progress mode.
*/
public void setIndeterminate(boolean indeterminate) {
this.indeterminate = indeterminate;
}
/**
* Gets the outline color.
*
* @return Outline color of the empty ring.
*/
public int getOutlineColor() {
return outlineColor;
}
/**
* Gets the filled ring color.
*
* @return Returns the filled ring color.
*/
public int getRingColor() {
return ringColor;
}
/**
* Gets the color of the inner circle.
*
* @return Inner circle color.
*/
public int getCenterColor() {
return centerColor;
}
/**
* Sets the empty progress outline color.
*
* @param outlineColor Outline color in #AARRGGBB format.
*/
public void setOutlineColor(int outlineColor) {
this.outlineColor = outlineColor;
invalidateSelf();
}
/**
* Sets the progress ring color.
*
* @param ringColor Ring color in #AARRGGBB format.
*/
public void setRingColor(int ringColor) {
this.ringColor = ringColor;
invalidateSelf();
}
/**
* Sets the inner circle color.
*
* @param centerColor Inner circle color in #AARRGGBB format.
*/
public void setCenterColor(int centerColor) {
this.centerColor = centerColor;
invalidateSelf();
}
/**
* Helper class to manage the creation of a CircularProgressDrawable
*
* @author Saul Diaz <sefford@gmail.com>
*/
public static class Builder {
/**
* Witdh of the stroke of the filled ring
*/
int ringWidth;
/**
* Color of the outline of the empty ring in #AARRGGBB mode.
*/
int outlineColor;
/**
* Color of the filled ring in #AARRGGBB mode.
*/
int ringColor;
/**
* Color of the inner circle in #AARRGGBB mode.
*/
int centerColor;
/**
* Scale between the outer ring and the inner circle
*/
float circleScale = 0.75f;
/**
* Sets the ring width.
*
* @param ringWidth Default ring width
* @return This builder
*/
public Builder setRingWidth(int ringWidth) {
this.ringWidth = ringWidth;
return this;
}
/**
* Sets the default empty outer ring outline color.
*
* @param outlineColor Outline color in #AARRGGBB format.
* @return
*/
public Builder setOutlineColor(int outlineColor) {
this.outlineColor = outlineColor;
return this;
}
/**
* Sets the progress ring color.
*
* @param ringColor Ring color in #AARRGGBB format.
* @returns This Builder
*/
public Builder setRingColor(int ringColor) {
this.ringColor = ringColor;
return this;
}
/**
* Sets the inner circle color.
*
* @param centerColor Inner circle color in #AARRGGBB format.
* @return This builder
*/
public Builder setCenterColor(int centerColor) {
this.centerColor = centerColor;
return this;
}
/**
* Sets the inner circle scale. Defaults to 0.75.
*
* @param circleScale Inner circle scale.
* @return This builder
*/
public Builder setInnerCircleScale(float circleScale) {
this.circleScale = circleScale;
return this;
}
/**
* Creates a new CircularProgressDrawable with the requested parameters
*
* @return New CircularProgressDrawableInstance
*/
public CircularProgressDrawable create() {
return new CircularProgressDrawable(ringWidth, circleScale, outlineColor, ringColor, centerColor);
}
}
}
没错 ,看到这么多英文注释。确实是github找的。能实现效果就好