如何在android中制作自定义虚线圆形进度条?

时间:2016-06-14 09:09:51

标签: android

我搜索了虚线圆形进度条但是我得到了任何完美的例子,有圆形进度条但没有点缀一个所以我已经实现了希望它可以帮助某人,你可以将它作为参考并进一步定制,对于初学者来说,它将有助于理解代码,因为它在每行上对它所做的事情进行了评论。

3 个答案:

答案 0 :(得分:6)

<强> MainActivity.java

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}
}

<强> activity_main.xml中:

&#13;
&#13;
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.naveenbm.customcircleprogressbar.MainActivity"
    >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center">

        <com.example.custom.customcircleprogressbar.CricleProgressBarCustom
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            ></com.example.custom.customcircleprogressbar.CricleProgressBarCustom>

    </RelativeLayout>

</RelativeLayout>
&#13;
&#13;
&#13;

<强> CircleProgressBarCustom.java

public class CricleProgressBarCustom extends View {

//Normal dot radius
private int dotRadius = 10;

//Expanded Dot Radius
private int bounceDotRadius = 13;

//to get identified in which position dot has to expand its radius
private int dotPosition = 1;

//specify how many dots you need in a progressbar
private int dotAmount = 10;

//specify the circle radius
private int circleRadius = 50;


public CricleProgressBarCustom(Context context) {
    super(context);
}

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

public CricleProgressBarCustom(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    //Animation called when attaching to the window, i.e to your screen
    startAnimation();
}


@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //take the point to the center of the screen
    canvas.translate(this.getWidth()/2,this.getHeight()/2);

    Paint progressPaint = new Paint();
    progressPaint.setColor(Color.parseColor("#ff014e"));

    //call create dot method
    createDotInCircle(canvas,progressPaint);
}

private void createDotInCircle(Canvas canvas,Paint progressPaint) {
    //angle for each dot angle = (360/number of dots) i.e  (360/10)
    int angle = 36;

    for(int i = 1; i <= dotAmount; i++){

        if(i == dotPosition){
             // angle should be in radians  i.e formula (angle *(Math.PI / 180))
            float x = (float) (circleRadius * (Math.cos((angle * i) * (Math.PI / 180))));
            float y = (float) (circleRadius * (Math.sin((angle * i) * (Math.PI / 180))));

            canvas.drawCircle(x,y, bounceDotRadius, progressPaint);

        }else{
            // angle should be in radians  i.e formula (angle *(Math.PI / 180))
            float x = (float) (circleRadius * (Math.cos((angle * i) * (Math.PI / 180))));
            float y = (float) (circleRadius * (Math.sin((angle * i) * (Math.PI / 180))));

            canvas.drawCircle(x,y, dotRadius, progressPaint);

        }

    }
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    int width = 0;
    int height = 0;

    //Dynamically setting width and height to progressbar 100 is circle radius, dotRadius * 3 to cover the width and height of Progressbar
     width = 100 + (dotRadius*3);
     height = 100 + (dotRadius*3);

    //MUST CALL THIS
    setMeasuredDimension(width, height);
}

private void startAnimation() {
    BounceAnimation bounceAnimation = new BounceAnimation();
    bounceAnimation.setDuration(150);
    bounceAnimation.setRepeatCount(Animation.INFINITE);
    bounceAnimation.setInterpolator(new LinearInterpolator());
    bounceAnimation.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {

        }

        @Override
        public void onAnimationEnd(Animation animation) {

        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            dotPosition++;
            //when dotPosition == dotAmount , then start again applying animation from 0th positon , i.e  dotPosition = 0;
            if (dotPosition > dotAmount) {
                dotPosition = 1;
            }


        }
    });
    startAnimation(bounceAnimation);
}


private class BounceAnimation extends Animation {
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        super.applyTransformation(interpolatedTime, t);
        //call invalidate to redraw your view againg.
        invalidate();
    }
}
}

快照:

enter image description here

答案 1 :(得分:1)

我可以建议您使用顺畅工作的各种进度条

https://github.com/ybq/Android-SpinKit

你把课程......

如果你想要圆形进度条而不是它的工作..

将TextView放在您想要的位置......

首先采取..在你使用的班级。(声明)

   private Circle mCircleDrawable = new Circle();

比在你的Oncreate中拿这个..

    mCircleDrawable.setBounds(0, 0, 100, 100);
    mCircleDrawable.setColor(R.color.colorPrimary);// What u want of color progress bar dots...

TextView progressBar_text=(TextView)findViewById(R.id.progress);// Your Textview..
    progressBar_text.setCompoundDrawables(null, null, mCircleDrawable, null);// Set Progress bar on Textview..

您需要启动

    mCircleDrawable.start();

退出时也可以停止循环。 On Detroyed或PostMethod ..如果使用(AYSNC)

mCircleDrawable.stop();

用于此的类...

您可以使用所有库,并使用上链接示例

获取所需的任何进度条

Circle.java

import android.animation.ValueAnimator;

import com.github.ybq.android.spinkit.animation.SpriteAnimatorBuilder;
import com.github.ybq.android.spinkit.sprite.CircleSprite;
import com.github.ybq.android.spinkit.sprite.CircleSpriteGroup;
import com.github.ybq.android.spinkit.sprite.Sprite;


 public class Circle extends CircleSpriteGroup {

@Override
public Sprite[] onCreateChild() {
    Dot[] dots = new Dot[12];
    for (int i = 0; i < dots.length; i++) {
        dots[i] = new Dot();
        dots[i].setAnimationDelay(1200 / 12 * i + -1200);
    }
    return dots;
}

class Dot extends CircleSprite {

    public Dot() {
        setScale(0f);
    }

    @Override
    public ValueAnimator getAnimation() {
        float fractions[] = new float[]{0f, 0.5f, 1f};
        return new SpriteAnimatorBuilder(this).
                scale(fractions, 0f, 1f, 0f).
                duration(1200).
                easeInOut(fractions)
                .build();
    }
}
}

SpriteAnimatorBuilder.Java

import android.animation.Keyframe;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.util.Property;
import android.view.animation.Animation;
import android.view.animation.Interpolator;


import    com.github.ybq.android.spinkit.animation.interpolator.KeyFrameInterpolator;
import com.github.ybq.android.spinkit.sprite.Sprite;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;


public class SpriteAnimatorBuilder {
private Sprite sprite;
private List<PropertyValuesHolder> propertyValuesHolders = new ArrayList<>  ();
private Interpolator interpolator;
private int repeatCount = Animation.INFINITE;
private long duration = 2000;

public SpriteAnimatorBuilder(Sprite sprite) {
    this.sprite = sprite;
}

public SpriteAnimatorBuilder scale(float fractions[], float... scale) {
    holder(fractions, Sprite.SCALE, scale);
    return this;
}

public SpriteAnimatorBuilder alpha(float fractions[], int... alpha) {
    holder(fractions, Sprite.ALPHA, alpha);
    return this;
}

@SuppressWarnings("unused")
public SpriteAnimatorBuilder scaleX(float fractions[], float... scaleX) {
    holder(fractions, Sprite.SCALE, scaleX);
    return this;
}

public SpriteAnimatorBuilder scaleY(float fractions[], float... scaleY) {
    holder(fractions, Sprite.SCALE_Y, scaleY);
    return this;
}

public SpriteAnimatorBuilder rotateX(float fractions[], int... rotateX) {
    holder(fractions, Sprite.ROTATE_X, rotateX);
    return this;
}

public SpriteAnimatorBuilder rotateY(float fractions[], int... rotateY) {
    holder(fractions, Sprite.ROTATE_Y, rotateY);
    return this;
}

@SuppressWarnings("unused")
public SpriteAnimatorBuilder translateX(float fractions[], int... translateX) {
    holder(fractions, Sprite.TRANSLATE_X, translateX);
    return this;
}


@SuppressWarnings("unused")
public SpriteAnimatorBuilder translateY(float fractions[], int... translateY) {
    holder(fractions, Sprite.TRANSLATE_Y, translateY);
    return this;
}


public SpriteAnimatorBuilder rotate(float fractions[], int... rotate) {
    holder(fractions, Sprite.ROTATE, rotate);
    return this;
}

public SpriteAnimatorBuilder translateXPercentage(float fractions[], float... translateXPercentage) {
    holder(fractions, Sprite.TRANSLATE_X_PERCENTAGE, translateXPercentage);
    return this;
}

public SpriteAnimatorBuilder translateYPercentage(float[] fractions, float... translateYPercentage) {
    holder(fractions, Sprite.TRANSLATE_Y_PERCENTAGE, translateYPercentage);
    return this;
}

public PropertyValuesHolder holder(float[] fractions, Property property, float[] values) {
    ensurePair(fractions.length, values.length);
    Keyframe[] keyframes = new Keyframe[fractions.length];
    for (int i = 0; i < values.length; i++) {
        keyframes[i] = Keyframe.ofFloat(fractions[i], values[i]);
    }
    PropertyValuesHolder valuesHolder = PropertyValuesHolder.
            ofKeyframe(property
                    , keyframes
            );
    propertyValuesHolders.add(valuesHolder);
    return valuesHolder;
}

public PropertyValuesHolder holder(float[] fractions, Property property, int[] values) {
    ensurePair(fractions.length, values.length);
    Keyframe[] keyframes = new Keyframe[fractions.length];
    for (int i = 0; i < values.length; i++) {
        keyframes[i] = Keyframe.ofInt(fractions[i], values[i]);
    }
    PropertyValuesHolder valuesHolder = PropertyValuesHolder.
            ofKeyframe(property
                    , keyframes
            );
    propertyValuesHolders.add(valuesHolder);
    return valuesHolder;
}

private void ensurePair(int fractionsLength, int valuesLength) {
    if (fractionsLength != valuesLength) {
        throw new IllegalStateException(String.format(
                Locale.getDefault(),
                "The fractions.length must equal values.length, " +
                        "fraction.length[%d], values.length[%d]",
                fractionsLength,
                valuesLength));
    }
}


public SpriteAnimatorBuilder interpolator(Interpolator interpolator) {
    this.interpolator = interpolator;
    return this;
}

public SpriteAnimatorBuilder easeInOut(float... fractions) {
    interpolator(KeyFrameInterpolator.easeInOut(
            fractions
    ));
    return this;
}


public SpriteAnimatorBuilder duration(long duration) {
    this.duration = duration;
    return this;
}

@SuppressWarnings("unused")
public SpriteAnimatorBuilder repeatCount(int repeatCount) {
    this.repeatCount = repeatCount;
    return this;
}


public ObjectAnimator build() {
    PropertyValuesHolder[] holders = new PropertyValuesHolder[propertyValuesHolders.size()];
    ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(sprite,
            propertyValuesHolders.toArray(holders));
    animator.setDuration(duration);
    animator.setRepeatCount(repeatCount);
    animator.setInterpolator(interpolator);
    return animator;
}

}

CircleSprite.java

import android.animation.ValueAnimator;
import android.graphics.Canvas;
import android.graphics.Paint;


public class CircleSprite extends ShapeSprite {

@Override
public ValueAnimator getAnimation() {
    return null;
}

@Override
public void drawShape(Canvas canvas, Paint paint) {
    if (getDrawBounds() != null) {
        int radius = Math.min(getDrawBounds().width(), getDrawBounds().height()) / 2;
        canvas.drawCircle(getDrawBounds().centerX(),
                getDrawBounds().centerY(),
                radius, paint);
    }
}
}

ShapeSprite .java

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;


 public abstract class ShapeSprite extends Sprite {

 private Paint mPaint;
 private int mUseColor;
private int mBaseColor;

 public ShapeSprite() {
     setColor(Color.WHITE);
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setColor(mUseColor);
}

@Override
public void setColor(int color) {
    mBaseColor = color;
    updateUseColor();
}

@Override
public int getColor() {
    return mBaseColor;
}

@SuppressWarnings("unused")
public int getUseColor() {
    return mUseColor;
}

@Override
public void setAlpha(int alpha) {
    super.setAlpha(alpha);
    updateUseColor();
}

private void updateUseColor() {
    int alpha = getAlpha();
    alpha += alpha >> 7;
    final int baseAlpha = mBaseColor >>> 24;
    final int useAlpha = baseAlpha * alpha >> 8;
    mUseColor = (mBaseColor << 8 >>> 8) | (useAlpha << 24);
}

@Override
public void setColorFilter(ColorFilter colorFilter) {
    mPaint.setColorFilter(colorFilter);
}

@Override
protected final void drawSelf(Canvas canvas) {
    mPaint.setColor(mUseColor);
    drawShape(canvas, mPaint);
}

public abstract void drawShape(Canvas canvas, Paint paint);

}

CircleSpriteGroup .java

import android.graphics.Canvas;
import android.graphics.Rect;


 public abstract class CircleSpriteGroup extends SpriteGroup {

@Override
public void drawChild(Canvas canvas) {
    for (int i = 0; i < getChildCount(); i++) {
        Sprite sprite = getChildAt(i);
        int count = canvas.save();
        canvas.rotate(i * 360 / getChildCount(),
                getBounds().centerX(),
                getBounds().centerY());
        sprite.draw(canvas);
        canvas.restoreToCount(count);
    }
}

@Override
protected void onBoundsChange(Rect bounds) {
    super.onBoundsChange(bounds);
    bounds = clipSquare(bounds);
    int radius = (int) (bounds.width() * Math.PI / 3.6f / getChildCount());
    int left = bounds.centerX() - radius;
    int right = bounds.centerX() + radius;
    for (int i = 0; i < getChildCount(); i++) {
        Sprite sprite = getChildAt(i);
        sprite.setDrawBounds(left, bounds.top, right, bounds.top + radius * 2);
    }
}
  }

Sprite.java

 import android.animation.ValueAnimator;
 import android.graphics.Camera;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.Matrix;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.drawable.Animatable;
 import android.graphics.drawable.Drawable;
 import android.util.Property;

 import com.github.ybq.android.spinkit.animation.AnimationUtils;
 import com.github.ybq.android.spinkit.animation.FloatProperty;
 import com.github.ybq.android.spinkit.animation.IntProperty;


public abstract class Sprite extends Drawable implements
    ValueAnimator.AnimatorUpdateListener
    , Animatable
    , Drawable.Callback {

private float scale = 1;
private float scaleX = 1;
private float scaleY = 1;
private float pivotX;
private float pivotY;
private int animationDelay;
private int rotateX;
private int rotateY;
private int translateX;
private int translateY;
private int rotate;
private float translateXPercentage;
private float translateYPercentage;
private ValueAnimator animator;
private int alpha = 255;
private static final Rect ZERO_BOUNDS_RECT = new Rect();
protected Rect drawBounds = ZERO_BOUNDS_RECT;
private Camera mCamera;
private Matrix mMatrix;

public Sprite() {
    mCamera = new Camera();
    mMatrix = new Matrix();
}

public abstract int getColor();

public abstract void setColor(int color);

@Override
public void setAlpha(int alpha) {
    this.alpha = alpha;
}

@Override
public int getAlpha() {
    return alpha;
}

@Override
public int getOpacity() {
    return PixelFormat.RGBA_8888;
}

public float getTranslateXPercentage() {
    return translateXPercentage;
}

public void setTranslateXPercentage(float translateXPercentage) {
    this.translateXPercentage = translateXPercentage;
}

public float getTranslateYPercentage() {
    return translateYPercentage;
}

public void setTranslateYPercentage(float translateYPercentage) {
    this.translateYPercentage = translateYPercentage;
}

public int getTranslateX() {
    return translateX;
}

public void setTranslateX(int translateX) {
    this.translateX = translateX;
}

public int getTranslateY() {
    return translateY;
}

public void setTranslateY(int translateY) {
    this.translateY = translateY;
}

public int getRotate() {
    return rotate;
}

public void setRotate(int rotate) {
    this.rotate = rotate;
}

public float getScale() {
    return scale;
}

public void setScale(float scale) {
    this.scale = scale;
    setScaleX(scale);
    setScaleY(scale);
}

public float getScaleX() {
    return scaleX;
}

public void setScaleX(float scaleX) {
    this.scaleX = scaleX;
}

public float getScaleY() {
    return scaleY;
}

public void setScaleY(float scaleY) {
    this.scaleY = scaleY;
}

public int getRotateX() {
    return rotateX;
}

public void setRotateX(int rotateX) {
    this.rotateX = rotateX;
}

public int getRotateY() {
    return rotateY;
}

public void setRotateY(int rotateY) {
    this.rotateY = rotateY;
}

public float getPivotX() {
    return pivotX;
}

public void setPivotX(float pivotX) {
    this.pivotX = pivotX;
}

public float getPivotY() {
    return pivotY;
}

public void setPivotY(float pivotY) {
    this.pivotY = pivotY;
}

@SuppressWarnings("unused")
public int getAnimationDelay() {
    return animationDelay;
}

public Sprite setAnimationDelay(int animationDelay) {
    this.animationDelay = animationDelay;
    return this;
}

@Override
public void setColorFilter(ColorFilter colorFilter) {

}

public abstract ValueAnimator getAnimation();

@Override
public void start() {
    if (AnimationUtils.isStarted(animator)) {
        return;
    }

    animator = obtainAnimation();
    if (animator == null) {
        return;
    }

    AnimationUtils.start(animator);
    invalidateSelf();
}

public ValueAnimator obtainAnimation() {
    if (animator == null) {
        animator = getAnimation();
    }
    if (animator != null) {
        animator.addUpdateListener(this);
        animator.setStartDelay(animationDelay);
    }
    return animator;
}

@Override
public void stop() {
    if (AnimationUtils.isStarted(animator)) {
        animator.removeAllUpdateListeners();
        animator.end();
        reset();
    }
}

protected abstract void drawSelf(Canvas canvas);

public void reset() {
    scale = 1;
    rotateX = 0;
    rotateY = 0;
    translateX = 0;
    translateY = 0;
    rotate = 0;
    translateXPercentage = 0f;
    translateYPercentage = 0f;
}

@Override
public boolean isRunning() {
    return AnimationUtils.isRunning(animator);
}

@Override
protected void onBoundsChange(Rect bounds) {
    super.onBoundsChange(bounds);
    setDrawBounds(bounds);
}

public void setDrawBounds(Rect drawBounds) {
    setDrawBounds(drawBounds.left, drawBounds.top, drawBounds.right, drawBounds.bottom);
}

public void setDrawBounds(int left, int top, int right, int bottom) {
    this.drawBounds = new Rect(left, top, right, bottom);
    setPivotX(getDrawBounds().centerX());
    setPivotY(getDrawBounds().centerY());
}

@Override
public void invalidateDrawable(Drawable who) {
    invalidateSelf();
}

@Override
public void scheduleDrawable(Drawable who, Runnable what, long when) {

}

@Override
public void unscheduleDrawable(Drawable who, Runnable what) {

}

@Override
public void onAnimationUpdate(ValueAnimator animation) {
    final Callback callback = getCallback();
    if (callback != null) {
        callback.invalidateDrawable(this);
    }
}

public Rect getDrawBounds() {
    return drawBounds;
}

@Override
public void draw(Canvas canvas) {
    int tx = getTranslateX();
    tx = tx == 0 ? (int) (getBounds().width() * getTranslateXPercentage()) : tx;
    int ty = getTranslateY();
    ty = ty == 0 ? (int) (getBounds().height() * getTranslateYPercentage()) : ty;
    canvas.translate(tx, ty);
    canvas.scale(getScaleX(), getScaleY(), getPivotX(), getPivotY());
    canvas.rotate(getRotate(), getPivotX(), getPivotY());

    if (getRotateX() != 0 || getRotateY() != 0) {
        mCamera.save();
        mCamera.rotateX(getRotateX());
        mCamera.rotateY(getRotateY());
        mCamera.getMatrix(mMatrix);
        mMatrix.preTranslate(-getPivotX(), -getPivotY());
        mMatrix.postTranslate(getPivotX(), getPivotY());
        mCamera.restore();
        canvas.concat(mMatrix);
    }
    drawSelf(canvas);
}

public Rect clipSquare(Rect rect) {
    int w = rect.width();
    int h = rect.height();
    int min = Math.min(w, h);
    int cx = rect.centerX();
    int cy = rect.centerY();
    int r = min / 2;
    return new Rect(
            cx - r,
            cy - r,
            cx + r,
            cy + r
    );
}

public static final Property<Sprite, Integer> ROTATE_X = new IntProperty<Sprite>("rotateX") {
    @Override
    public void setValue(Sprite object, int value) {
        object.setRotateX(value);
    }

    @Override
    public Integer get(Sprite object) {
        return object.getRotateX();
    }
};

public static final Property<Sprite, Integer> ROTATE = new IntProperty<Sprite>("rotate") {
    @Override
    public void setValue(Sprite object, int value) {
        object.setRotate(value);
    }

    @Override
    public Integer get(Sprite object) {
        return object.getRotate();
    }
};

public static final Property<Sprite, Integer> ROTATE_Y = new IntProperty<Sprite>("rotateY") {
    @Override
    public void setValue(Sprite object, int value) {
        object.setRotateY(value);
    }

    @Override
    public Integer get(Sprite object) {
        return object.getRotateY();
    }
};

@SuppressWarnings("unused")
public static final Property<Sprite, Integer> TRANSLATE_X = new IntProperty<Sprite>("translateX") {
    @Override
    public void setValue(Sprite object, int value) {
        object.setTranslateX(value);
    }

    @Override
    public Integer get(Sprite object) {
        return object.getTranslateX();
    }
};

@SuppressWarnings("unused")
public static final Property<Sprite, Integer> TRANSLATE_Y = new IntProperty<Sprite>("translateY") {
    @Override
    public void setValue(Sprite object, int value) {
        object.setTranslateY(value);
    }

    @Override
    public Integer get(Sprite object) {
        return object.getTranslateY();
    }
};

public static final Property<Sprite, Float> TRANSLATE_X_PERCENTAGE = new FloatProperty<Sprite>("translateXPercentage") {
    @Override
    public void setValue(Sprite object, float value) {
        object.setTranslateXPercentage(value);
    }

    @Override
    public Float get(Sprite object) {
        return object.getTranslateXPercentage();
    }
};

public static final Property<Sprite, Float> TRANSLATE_Y_PERCENTAGE = new FloatProperty<Sprite>("translateYPercentage") {
    @Override
    public void setValue(Sprite object, float value) {
        object.setTranslateYPercentage(value);
    }

    @Override
    public Float get(Sprite object) {
        return object.getTranslateYPercentage();
    }
};

@SuppressWarnings("unused")
public static final Property<Sprite, Float> SCALE_X = new FloatProperty<Sprite>("scaleX") {
    @Override
    public void setValue(Sprite object, float value) {
        object.setScaleX(value);
    }

    @Override
    public Float get(Sprite object) {
        return object.getScaleX();
    }
};

public static final Property<Sprite, Float> SCALE_Y = new FloatProperty<Sprite>("scaleY") {
    @Override
    public void setValue(Sprite object, float value) {
        object.setScaleY(value);
    }

    @Override
    public Float get(Sprite object) {
        return object.getScaleY();
    }
};

public static final Property<Sprite, Float> SCALE = new FloatProperty<Sprite>("scale") {
    @Override
    public void setValue(Sprite object, float value) {
        object.setScale(value);
    }

    @Override
    public Float get(Sprite object) {
        return object.getScale();
    }
};

public static final Property<Sprite, Integer> ALPHA = new IntProperty<Sprite>("alpha") {
    @Override
    public void setValue(Sprite object, int value) {
        object.setAlpha(value);
    }

    @Override
    public Integer get(Sprite object) {
        return object.getAlpha();
    }
};

   }

KeyFrameInterpolator.java

 import android.animation.TimeInterpolator;
 import android.view.animation.Interpolator;


 public class KeyFrameInterpolator implements Interpolator {

private TimeInterpolator interpolator;
private float[] fractions;


public static KeyFrameInterpolator easeInOut(float... fractions) {
    KeyFrameInterpolator interpolator = new KeyFrameInterpolator(Ease.inOut());
    interpolator.setFractions(fractions);
    return interpolator;
}

public KeyFrameInterpolator(TimeInterpolator interpolator) {
    this.interpolator = interpolator;
}

public void setFractions(float... fractions) {
    this.fractions = fractions;
}

@Override
public synchronized float getInterpolation(float input) {
    if (fractions.length > 1) {
        for (int i = 0; i < fractions.length - 1; i++) {
            float start = fractions[i];
            float end = fractions[i + 1];
            float duration = end - start;
            if (input >= start && input <= end) {
                input = (input - start) / duration;
                return start + (interpolator.getInterpolation(input)
                        * duration);
            }
        }
    }
    return interpolator.getInterpolation(input);
}
 }

AnimationUtils.java

import android.animation.Animator;
import android.animation.ValueAnimator;

import com.github.ybq.android.spinkit.sprite.Sprite;

public class AnimationUtils {

public static void start(Animator animator) {
    if (animator != null && !animator.isStarted()) {
        animator.start();
    }
}

public static void stop(Animator animator) {
    if (animator != null && !animator.isRunning()) {
        animator.end();
    }
}

public static void start(Sprite... sprites) {
    for (Sprite sprite : sprites) {
        sprite.start();
    }
}

public static void stop(Sprite... sprites) {
    for (Sprite sprite : sprites) {
        sprite.stop();
    }
}

public static boolean isRunning(Sprite... sprites) {
    for (Sprite sprite : sprites) {
        if (sprite.isRunning()) {
            return true;
        }
    }
    return false;
}

public static boolean isRunning(ValueAnimator animator) {
    return animator != null && animator.isRunning();
}

public static boolean isStarted(ValueAnimator animator) {
    return animator != null && animator.isStarted();
}
}

FloatProperty.java

 import android.util.Property;


 public abstract class FloatProperty<T> extends Property<T, Float> {

public FloatProperty(String name) {
    super(Float.class, name);
}

/**
 * A type-specific override of the {@link #set(Object, Float)} that is faster when dealing
 * with fields of type <code>float</code>.
 */
public abstract void setValue(T object, float value);

@Override
final public void set(T object, Float value) {
    setValue(object, value);
}

   }

IntProperty.java

 import android.util.Property;


 public abstract class IntProperty<T> extends Property<T, Integer> {

 public IntProperty(String name) {
    super(Integer.class, name);
}


 public abstract void setValue(T object, int value);

@Override
final public void set(T object, Integer value) {
    setValue(object, value);
}

}

答案 2 :(得分:0)

great answer from @Naveen Shriyan 的科特琳方式:

class CustomDottedProgressBar : View {

constructor(context: Context) : super(context)

constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)

constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)

//Normal dot radius
private val dotRadius = 10F

//Expanded Dot Radius
private val bounceDotRadius = 15F

//to get identified in which position dot has to expand its radius
private var dotPosition = 0

//specify the circle radius
private val circleRadius = 50

// specify the sizes of dots
private val dotRadiusList = arrayListOf(2F, 3F, 4F, 5F, 6F, 7F, 8F, 9F, 10F)

//specify how many dots you need in a progressbar
private val dotAmount = dotRadiusList.size

private val progressPaint = Paint()

override fun onAttachedToWindow() {
    super.onAttachedToWindow()
    //Animation called when attaching to the window, i.e to your screen
    startAnimation()
}

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    //take the point to the center of the screen
    canvas.translate((this.width / 2).toFloat(), (this.height / 2).toFloat())
    progressPaint.color = context.getColor(R.color.orange)

    //call create dot method
    createDotInCircle(canvas, progressPaint)
}

private fun createDotInCircle(canvas: Canvas, progressPaint: Paint) {
    //angle for each dot angle = (360/number of dots) i.e  (360/10)
    val angle = 360 / dotAmount
    for (i in 0 until dotAmount) {
        if (i == dotPosition) {
            // angle should be in radians  i.e formula (angle *(Math.PI / 180))
            val x = (circleRadius * cos(angle * i * (Math.PI / 180))).toFloat()
            val y = (circleRadius * sin(angle * i * (Math.PI / 180))).toFloat()
            canvas.drawCircle(x, y, bounceDotRadius, progressPaint)
        } else {
            // angle should be in radians  i.e formula (angle *(Math.PI / 180))
            val x = (circleRadius * cos(angle * i * (Math.PI / 180))).toFloat()
            val y = (circleRadius * sin(angle * i * (Math.PI / 180))).toFloat()
            canvas.drawCircle(x, y, dotRadiusList[i], progressPaint)
        }
    }
}

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec)

    //Dynamically setting width and height to progressbar 100 is circle radius, dotRadius * 3 to cover the width and height of Progressbar
    val width = 100 + dotRadius * 3
    val height = 100 + dotRadius * 3

    //MUST CALL THIS
    setMeasuredDimension(width.roundToInt(), height.roundToInt())
}

private fun startAnimation() {
    val bounceAnimation = BounceAnimation()
    bounceAnimation.duration = 75
    bounceAnimation.repeatCount = Animation.INFINITE
    bounceAnimation.interpolator = LinearInterpolator()
    bounceAnimation.setAnimationListener(object : Animation.AnimationListener {
        override fun onAnimationStart(animation: Animation) {}
        override fun onAnimationEnd(animation: Animation) {}
        override fun onAnimationRepeat(animation: Animation) {
            dotPosition++
            //when dotPosition == dotAmount , then start again applying animation from 0th position , i.e  dotPosition = 0;
            if (dotPosition > dotAmount) {
                dotPosition = 0
            }
        }
    })
    startAnimation(bounceAnimation)
}

private inner class BounceAnimation : Animation() {
    override fun applyTransformation(interpolatedTime: Float, t: Transformation?) {
        super.applyTransformation(interpolatedTime, t)
        //call invalidate to redraw your view again.
        invalidate()
    }
}}