Android 运动小球加载效果

只愿长相守 提交于 2020-03-02 11:18:45

一、效果图

二、代码实现


public class LoadingView extends View {

    private static final long ANIMATION_TIMEOUT = 1500;
    private TextPaint mPaint;
    private int mMaxRadius;
    private int mDotWidth;
    private int mColor = Color.TRANSPARENT;
    private AnimatorSet mCircleDotAnimatorSet;

    private  float[] mDotAngles = null;

    public final static int LINE_STYLE_DOT =0;
    public final static int LINE_STYLE_ARC =1;
    private int mLineStyle = LINE_STYLE_DOT;

    public LoadingView(Context context) {
        this(context,null);
    }

    public LoadingView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public LoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint();
    }


    public void setLineStyle(int mLineStyle) {
        this.mLineStyle = mLineStyle;
        if(mLineStyle==LINE_STYLE_DOT) {
            mDotWidth = (int) dip2px(8);
        }else{
            mDotWidth = (int) dip2px(3);
        }
    }

    public float dip2px(int dp){
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dp,getResources().getDisplayMetrics());
    }


    private void initPaint() {
        // 实例化画笔并打开抗锯齿
        mPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG );
        mPaint.setAntiAlias(true);
        mPaint.setPathEffect(new CornerPathEffect(10)); //设置线条类型
        mPaint.setStrokeWidth(dip2px(1));
        mPaint.setTextSize(dip2px((12)));
        mPaint.setStyle(Paint.Style.STROKE);

        mDotWidth = (int) dip2px(8);
        mColor = Color.BLUE;

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mDotAngles = null;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        if(widthMode!=MeasureSpec.EXACTLY){
            width = (int) dip2px(100);
        }
        if(heightMode!=MeasureSpec.EXACTLY){
            height = (int) dip2px(100);
        }
        setMeasuredDimension(width,height);

    }

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

        int width = getWidth();
        int height = getHeight();

        if(width==0 || height==0) return;

        int diameter = Math.min(width, height) / 2;
        mMaxRadius = diameter - mDotWidth /2;

        initPoints();

        int storeId = canvas.save();
        canvas.translate(width/2,height/2);

        if(mLineStyle==LINE_STYLE_DOT) {
            drawDotCircle(canvas);
        }else{
            drawArcCircle(canvas);
        }

        canvas.restoreToCount(storeId);

    }

    private void drawArcCircle(Canvas canvas) {

        if(mDotAngles==null || mDotAngles.length==0) return;
        int firstPointY = (int) (Math.sin(Math.toRadians(mDotAngles[0])) * mMaxRadius);
        int firstPointX = (int) (Math.cos(Math.toRadians(mDotAngles[0])) * mMaxRadius);

        int lastPointY = (int) (Math.sin(Math.toRadians(mDotAngles[mDotAngles.length-1])) * mMaxRadius);
        int lastPointX = (int) (Math.cos(Math.toRadians(mDotAngles[mDotAngles.length-1])) * mMaxRadius);

        double lineLenghtPower = Math.pow(firstPointY - lastPointY, 2) + Math.pow(firstPointX - lastPointX, 2);
        double length = Math.sqrt(lineLenghtPower)/2f;

        float degrees = (float) Math.toDegrees(Math.asin(length / mMaxRadius) ) *2;

        drawArcSport(canvas,mDotAngles[mDotAngles.length-1],degrees);
    }

    private void drawDotCircle(Canvas canvas) {

        if(mDotAngles==null) return;

        int color = mPaint.getColor();
        float strokeWidth = mPaint.getStrokeWidth();
        Paint.Cap strokeCap = mPaint.getStrokeCap();


        mPaint.setStrokeWidth(mDotWidth);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setColor(argb(255,0,0,255));

        for (int i = 0; i< mDotAngles.length; i++){
            double dotAngle = mDotAngles[i];
            int pointY = (int) (Math.sin(Math.toRadians(dotAngle)) * mMaxRadius);
            int pointX = (int) (Math.cos(Math.toRadians(dotAngle)) * mMaxRadius);
            canvas.drawPoint(pointX,pointY,mPaint);
        }

        mPaint.setColor(color);
        mPaint.setStrokeWidth(strokeWidth);
        mPaint.setStrokeCap(strokeCap);
    }

    private void initPoints() {
        if(mDotAngles !=null && mDotAngles.length==5) return;
        mDotAngles = new float[5];

        float dotRadius = mDotWidth /2f;

        float dotAngle = (float) Math.toDegrees(Math.atan(dotRadius/mMaxRadius)*2);

        for (int i = 0; i< mDotAngles.length; i++){
            float angle = 360f - (dotAngle+8)*(i+1);
            mDotAngles[i] = angle;
        }
        if(mCircleDotAnimatorSet!=null){
            mCircleDotAnimatorSet.cancel();
        }
        mCircleDotAnimatorSet = buildDotAnimationSet();
        mCircleDotAnimatorSet.start();
    }

    private AnimatorSet buildDotAnimationSet() {

        AnimatorSet animatorSet = new AnimatorSet();
        Animator[] animators = new Animator[mDotAngles.length];
        for (int i=0;i<mDotAngles.length;i++){
            Animator animator =   buildDotAnimation(mDotAngles[i],i);
            animator.setStartDelay(100*i);
            animators[i] = animator;
        }
        animatorSet.playTogether(animators);
        return animatorSet;
    }

    private Animator buildDotAnimation(final float startAngle, final int i) {

        ValueAnimator animatorTimer = ValueAnimator.ofFloat(0,1);
        animatorTimer.setDuration(ANIMATION_TIMEOUT);
        animatorTimer.setRepeatCount(ValueAnimator.INFINITE);
        animatorTimer.setInterpolator(new AccelerateDecelerateInterpolator());
        animatorTimer.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float fraction = animation.getAnimatedFraction();
                float angle = (float) (startAngle +  fraction*360);
                if(mDotAngles!=null){
                    mDotAngles[i] = angle;
                }
                if(i==0){
                    postInvalidate();
                }
            }
        });
        return animatorTimer;

    }


    public static int argb(
            @IntRange(from = 0, to = 255) int alpha,
            @IntRange(from = 0, to = 255) int red,
            @IntRange(from = 0, to = 255) int green,
            @IntRange(from = 0, to = 255) int blue) {
        return (alpha << 24) | (red << 16) | (green << 8) | blue;
    }


    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        try {
            if (mCircleDotAnimatorSet != null) {
                mCircleDotAnimatorSet.cancel();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private void drawArcSport(Canvas canvas,float currentAngle,float sweepAngle) {
        int oldColor = mPaint.getColor();
        Paint.Style style = mPaint.getStyle();
        float strokeWidth = mPaint.getStrokeWidth();

        mPaint.setStrokeWidth(mDotWidth);
        mPaint.setColor(mColor);
        mPaint.setStyle(Paint.Style.STROKE);

        canvas.drawArc(new RectF(-mMaxRadius,-mMaxRadius,mMaxRadius,mMaxRadius),currentAngle,sweepAngle,false,mPaint);
        mPaint.setColor(oldColor);
        mPaint.setStyle(style);
        mPaint.setStrokeWidth(strokeWidth);
    }
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!