美文网首页
加载中Loading ArrowDownloadButton

加载中Loading ArrowDownloadButton

作者: 菜鸟何时起飞 | 来源:发表于2020-05-25 17:30 被阅读0次
    arrowdownloadbutton.gif
     arrowDownloadButton.startAnimating();
            arrowDownloadButton.setProgress(50F);
    
    public class ArrowDownloadButton extends View {
    
        private static final int BLUE_ONE = Color.rgb(46, 164, 242);
        private static final int WHILE = Color.rgb(255, 255, 255);
        private static final float RADIUS = 180;
        private static final int TRI_POINT_NUMBER = 17;
        private static final float MAX_WAVE_HEIGHT = 10;
        private static final float MIN_WAVE_HEIGHT = 5;
        private static final int PROGRESS = 100;
        private static final int ANGLE = 360;
        private static final float TEXT_Y = 67.5f;
        private static final float OFFSET = 10;
        private static final float SMALL_RADIUS = 5;
        private static final float TEXT_SIZE = 40;
        private static final float ARC_WIDTH = 20;
        private static final float ARROW_WIDTH = 10;
        private static final float TRI_WIDTH = 10;
        private static final float LOADING_WIDTH = 10;
    
        private static final float STEP = 2;
        private static final float ELASTICITY_STEP = 10;
        private static final float ROPE_STEP_X = 30;
        private static final float ROPE_STEP_Y = 32;
        private static final float ROPE_HEAD_STEP_Y = 17;
        private static final float JUMP_STEP = 45;
        private static final float DOWN_STEP = 7.5f;
        private static final float TRI_STEP = 16.875f;
        private static final float TIME_STEP = 20;
        private static final float HOOK_STEP_Y = 15;
        private static final float HOOK_COUNT = 4;
        private static final float LITTLE_STEP = 8;
        private static final int DURATION = 20;
        private static final int COMPLETE_DURATION = 20;
    
        /**
         * start instance
         **/
        private static final String INSTANCE_STATE = "instance_state";
        /**
         *
         */
        private static final String X_I = "x";
        private static final String Y_I = "y";
        private static final String RADIUS_I = "radius";
        private static final String MAX_WAVE_HEIGHT_I = "max_wave_height";
        private static final String MIN_WAVE_HEIGHT_I = "min_wave_height";
        private static final String TEXT_Y_I = "text_y";
        private static final String STEP_I = "step";
        private static final String ELASTICITY_STEP_I = "elasticity_step";
        private static final String ROPE_STEP_X_I = "rope_step_x";
        private static final String ROPE_STEP_Y_I = "rope_step_y";
        private static final String ROPE_HEAD_STEP_Y_I = "rope_head_step_y";
        private static final String JUMP_STEP_I = "jump_step";
        private static final String DOWN_STEP_I = "down_step";
        private static final String TRI_STEP_I = "tri_step";
        private static final String HOOK_STEP_Y_I = "hook_step";
        private static final String LITTLE_STEP_I = "little_step";
        private static final String SMALL_RADIUS_I = "small_radius";
        private static final String TEXT_SIZE_I = "text_size";
        private static final String ARC_WIDTH_I = "arc_width";
        private static final String ARROW_WIDTH_I = "arrow_width";
        private static final String TRI_WIDTH_I = "tri_width";
        private static final String LOADING_WIDTH_I = "loading_width";
        private static final String IS_FIRST_I = "is_first";
        private static final String IS_ANIMATING_I = "is_animating";
        private static final String BEZIER_I = "bezier";
        private static final String IS_LOADING_I = "is_loading";
        private static final String IS_COMPLETED_I = "is_completed";
        private static final String IS_END_I = "is_end";
        private static final String COUNT_I = "count";
        private static final String LENGTH_I = "length";
        private static final String CURRENT_TIME_I = "current_time";
        private static final String WAVE_HEIGHT_I = "wave_height";
        private static final String PROGRESS_I = "progress";
        private static final String HOOK_COUNT_I = "hook_count";
        private static final String LENGTH_X_I = "length_x";
        private static final String LENGTH_Y_I = "length_y";
    
    
        private float x = 550;
        private float y = 550;
        private float radius = RADIUS;
        private float maxWaveHeight = MAX_WAVE_HEIGHT;
        private float minWaveHeight = MIN_WAVE_HEIGHT;
        private float textY = TEXT_Y;
        private float step = STEP;
        private float elasticityStep = ELASTICITY_STEP;
        private float ropeStepX = ROPE_STEP_X;
        private float ropeStepY = ROPE_STEP_Y;
        private float ropeHeadStepY = ROPE_HEAD_STEP_Y;
        private float jumpStep = JUMP_STEP;
        private float downStep = DOWN_STEP;
        private float triStep = TRI_STEP;
        private float hookStepY = HOOK_STEP_Y;
        private float littleStep = LITTLE_STEP;
        private float smallRadius = SMALL_RADIUS;
        private float textSize = TEXT_SIZE;
        private float arcWidth = ARC_WIDTH;
        private float arrowWidth = ARROW_WIDTH;
        private float triWidth = TRI_WIDTH;
        private float loadingWidth = LOADING_WIDTH;
    
        private Paint arrowPaint;
        private Paint arcPaint;
        private Paint smallPaint;
        private Paint triPaint;
        private Paint loadingPaint;
        private Paint textPaint;
    
        private Path arrowPath;
        private Path triPath;
        private Path textPath;
    
        private RectF oval;
    
        private Point a;
        private Point b;
        private Point c;
        private Point d;
        private Point e;
        private Point jumpPoint;
    
        private List<Point> triPoints = new ArrayList<>();
    
        private boolean isFirst = true;
        private boolean isAnimating = false;
        private boolean bezier = false;
        private boolean isLoading = false;
        private boolean isCompleted = false;
        private boolean isEnd = false;
        private int count = 0;
        private float length;
        private int currentTime = 0;
        private float waveHeight = MIN_WAVE_HEIGHT;
        private float progress = 0;
        private int hookCount = 0;
        float lengthX = 3 * radius / 4;
        float lengthY = 3 * radius / 4;
    
        public float getProgress() {
            return progress;
        }
    
        public void setProgress(float progress) {
            if (progress > 100) {
                this.progress = 100;
            } else {
                this.progress = progress;
            }
    
            if (progress == 100) {
                isLoading = false;
                isCompleted = true;
            }
        }
    
        public ArrowDownloadButton(Context context) {
            this(context, null);
        }
    
        public ArrowDownloadButton(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public ArrowDownloadButton(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            setMeasuredDimension(measure(widthMeasureSpec, true), measure(heightMeasureSpec, false));
        }
    
        private int measure(int measureSpec, boolean isWidth) {
            int result;
            int mode = MeasureSpec.getMode(measureSpec);
            int size = MeasureSpec.getSize(measureSpec);
            int padding = isWidth ? getPaddingLeft() + getPaddingRight() : getPaddingTop() + getPaddingBottom();
            if (mode == MeasureSpec.EXACTLY) {
                result = size;
            } else {
                result = isWidth ? getSuggestedMinimumWidth() : getSuggestedMinimumHeight();
                result += padding;
                if (mode == MeasureSpec.AT_MOST) {
                    if (isWidth) {
                        result = Math.max(result, size);
                    } else {
                        result = Math.min(result, size);
                    }
                }
            }
            return result;
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            if (isFirst) {
                init();
                isFirst = false;
            }
            canvas.drawCircle(x, y, radius, arcPaint);
            drawArrow(canvas);
            if (isAnimating) {
                animating();
            }
            if (isLoading) {
                loading(canvas);
            }
            if (isCompleted) {
                afterCompleted(canvas);
            }
        }
    
        private void init() {
            float temp = getHeight() > getWidth() ? getWidth() / 2 : getHeight() / 2;
            radius = temp - temp * OFFSET / RADIUS - temp * ELASTICITY_STEP / RADIUS - 6;
            x = getPaddingLeft() + getWidth() / 2;
            y = getPaddingTop() + getHeight() / 2;
            maxWaveHeight = convert(MAX_WAVE_HEIGHT);
            minWaveHeight = convert(MIN_WAVE_HEIGHT);
            textY = convert(TEXT_Y);
            step = convert(STEP);
            elasticityStep = convert(ELASTICITY_STEP);
            ropeStepX = convert(ROPE_STEP_X);
            ropeStepY = convert(ROPE_STEP_Y);
            ropeHeadStepY = convert(ROPE_HEAD_STEP_Y);
            jumpStep = convert(JUMP_STEP);
            downStep = convert(DOWN_STEP);
            triStep = convert(TRI_STEP);
            hookStepY = convert(HOOK_STEP_Y);
            littleStep = convert(LITTLE_STEP);
            smallRadius = convert(SMALL_RADIUS);
            textSize = convert(TEXT_SIZE);
            arcWidth = convert(ARC_WIDTH);
            arrowWidth = convert(ARROW_WIDTH);
            triWidth = convert(TRI_WIDTH);
            loadingWidth = convert(LOADING_WIDTH);
            lengthX = 3 * radius / 4;
            lengthY = 3 * radius / 4;
    
            arrowPath = new Path();
            triPath = new Path();
            textPath = new Path();
            oval = new RectF();
            oval.left = x - radius;
            oval.top = y - radius;
            oval.right = x + radius;
            oval.bottom = y + radius;
            length = radius / 2;
            initializePaints();
            initializePoints();
        }
    
        /**
         * start animating before loading
         */
        public void startAnimating() {
            isAnimating = true;
            invalidate();
        }
    
        /**
         * reset to initial state
         */
        public void reset() {
            isAnimating = false;
            isLoading = false;
            bezier = false;
            isCompleted = false;
            isEnd = false;
            length = radius / 2;
            count = 0;
            hookCount = 0;
            jumpPoint.x = -1;
            progress = 0;
            lengthX = 3 * radius / 4;
            lengthY = 3 * radius / 4;
            a.y = y + length;
            b.y = y - length;
            e.y = y + length;
            c.x = x - length / 2;
            c.y = y + length / 2;
            d.x = x + length / 2;
            d.y = y + length / 2;
            invalidate();
        }
    
        /**
         * animating
         */
        public void animating() {
            if (count < 19) {
                length = length * 3 / 4;
                a.y = y + length;
                b.y = y - length;
    
                if (((count + 1) % 3) == 0 && count < 9) {
                    e.y = e.y + step;
                    c.y = c.y + step;
                    d.y = d.y + step;
                }
                if (count > 8 && count < 12) {
                    jumpPoint.x = x;
                    jumpPoint.y = y - jumpStep * (count - 8);
                    c.x = c.x - ropeStepX;
                    c.y = c.y - ropeHeadStepY;
                    d.x = d.x + ropeStepX;
                    d.y = d.y - ropeHeadStepY;
                    e.y = e.y - ropeStepY;
                }
                if (count > 11) {
                    bezier = true;
                    if (count == 12) {
                        jumpPoint.y = jumpPoint.y - jumpStep * 2;
                    } else {
                        jumpPoint.y = jumpPoint.y + downStep;
                        if (count < 16) {
                            int time1 = 15 - count;
                            e.y = y + time1 * elasticityStep;
                        }
                    }
                }
                count++;
                postInvalidateDelayed(DURATION);
            } else {
                isAnimating = false;
                bezier = false;
                if (progress != 100) {
                    isLoading = true;
                } else {
                    isLoading = false;
                    isCompleted = true;
                }
            }
        }
    
        /**
         * under loading
         *
         * @param canvas Target Canvas
         */
        private void loading(Canvas canvas) {
            Point currentPoint = triPoints.get(0);
            Point nextPoint;
            for (int i = 0; i < TRI_POINT_NUMBER; i++) {
                Point p = triPoints.get(i);
                p.x = (x - 3 * radius / 4) + triStep * i;
                p.y = y + calculateTri(TIME_STEP * i, currentTime);
            }
            for (int i = 1; i < TRI_POINT_NUMBER; i++) {
                nextPoint = triPoints.get(i);
                triPath.reset();
                triPath.moveTo(currentPoint.x, currentPoint.y);
                triPath.lineTo(nextPoint.x, nextPoint.y);
                canvas.drawCircle(nextPoint.x, nextPoint.y, smallRadius, smallPaint);
                canvas.drawPath(triPath, triPaint);
                currentPoint = nextPoint;
            }
            textPath.moveTo(x - textSize, y + textY);
            textPath.lineTo(x + textSize, y + textY);
            canvas.drawTextOnPath((int) progress + "%", textPath, 0, 0, textPaint);
            currentTime = (int) (currentTime + TIME_STEP);
            float sweepAngle = (progress / PROGRESS * ANGLE);
            canvas.drawArc(oval, 270, 0 - sweepAngle, false, loadingPaint);
            postInvalidateDelayed(DURATION);
        }
    
        /**
         * the method do such things:
         * 1.draw arrow.
         * 2.when animate was completed, let the small ball jump.
         *
         * @param canvas Target Canvas
         */
        protected void drawArrow(Canvas canvas) {
            if (jumpPoint.x != -1) {
                canvas.drawCircle(jumpPoint.x, jumpPoint.y, smallRadius, smallPaint);
            }
            if (bezier) {
                arrowPath.reset();
                arrowPath.moveTo(c.x, c.y);
                arrowPath.quadTo(e.x, e.y, d.x, d.y);
                canvas.drawPath(arrowPath, arrowPaint);
            }  else if (isLoading) {
            } else if (isCompleted) {
            }  else if (isEnd) {
                canvas.drawCircle(x, y, radius, loadingPaint);
                drawArrowOrHook(canvas);
            } else {
                arrowPath.reset();
                arrowPath.moveTo(a.x, a.y);
                arrowPath.lineTo(b.x, b.y);
                canvas.drawPath(arrowPath, arrowPaint);
    
                canvas.drawCircle(a.x, a.y, smallRadius, smallPaint);
                canvas.drawCircle(b.x, b.y, smallRadius, smallPaint);
    
                drawArrowOrHook(canvas);
    
            }
        }
    
        /**
         * draw arrow or hook
         *
         * @param canvas Target Canvas
         */
        private void drawArrowOrHook(Canvas canvas) {
            arrowPath.reset();
            arrowPath.moveTo(e.x, e.y);
            arrowPath.lineTo(c.x, c.y);
            canvas.drawPath(arrowPath, arrowPaint);
            arrowPath.reset();
            arrowPath.moveTo(e.x, e.y);
            arrowPath.lineTo(d.x, d.y);
            canvas.drawPath(arrowPath, arrowPaint);
    
            canvas.drawCircle(c.x, c.y, smallRadius, smallPaint);
            canvas.drawCircle(d.x, d.y, smallRadius, smallPaint);
            canvas.drawCircle(e.x, e.y, smallRadius, smallPaint);
        }
    
        /**
         * the animate after loading
         *
         * @param canvas Target Canvas
         */
        private void afterCompleted(Canvas canvas) {
            canvas.drawCircle(x, y, radius, loadingPaint);
            if (hookCount == HOOK_COUNT - 1) {
                e.y = e.y + littleStep;
                c.x = c.x - littleStep;
                d.x = d.x + littleStep;
                d.y = d.y - littleStep;
                isCompleted = false;
                isEnd = true;
            } else {
                e.x = x;
                e.y = y + hookStepY * (hookCount + 1);
                lengthX = lengthX * 3 / 4;
                c.x = x - lengthX * 3 / 4;
                c.y = y;
                d.x = x + lengthY - radius / (float) 8 * (hookCount + 1);
                d.y = y - hookStepY * (hookCount + 1);
                hookCount++;
            }
            drawArrowOrHook(canvas);
            postInvalidateDelayed(COMPLETE_DURATION);
    
        }
    
        protected void initializePaints() {
            arcPaint = new Paint();
            arcPaint.setAntiAlias(true);
            arcPaint.setStyle(Paint.Style.STROKE);
            arcPaint.setStrokeWidth(arcWidth);
            arcPaint.setColor(BLUE_ONE);
    
            arrowPaint = new Paint();
            arrowPaint.setAntiAlias(true);
            arrowPaint.setStyle(Paint.Style.STROKE);
            arrowPaint.setStrokeWidth(arrowWidth);
            arrowPaint.setColor(WHILE);
    
            smallPaint = new Paint();
            smallPaint.setAntiAlias(true);
            smallPaint.setStyle(Paint.Style.FILL);
            smallPaint.setColor(WHILE);
    
            triPaint = new Paint();
            triPaint.setAntiAlias(true);
            triPaint.setStyle(Paint.Style.STROKE);
            triPaint.setStrokeWidth(triWidth);
            triPaint.setColor(WHILE);
    
            loadingPaint = new Paint();
            loadingPaint.setAntiAlias(true);
            loadingPaint.setStyle(Paint.Style.STROKE);
            loadingPaint.setStrokeWidth(loadingWidth);
            loadingPaint.setColor(WHILE);
    
            textPaint = new Paint();
            textPaint.setAntiAlias(true);
            textPaint.setStyle(Paint.Style.FILL);
            textPaint.setStrokeWidth(1);
            textPaint.setColor(WHILE);
            textPaint.setTextSize(textSize);
        }
    
        protected void initializePoints() {
            a = new Point(x, y + radius / 2);
            b = new Point(x, y - radius / 2);
            c = new Point(x - radius / 4, y + radius / 4);
            d = new Point(x + radius / 4, y + radius / 4);
            e = new Point(x, y + radius / 2);
            jumpPoint = new Point();
    
            for (int i = 0; i < TRI_POINT_NUMBER; i++) {
                Point point = new Point();
                point.x = (x - 3 * radius / 4) + triStep * i;
                point.y = y + calculateTri(TIME_STEP * i, 0);
                triPoints.add(point);
            }
        }
    
        /**
         * calculate the wave
         *
         * @param originalTime original time
         * @param currentTime  current time
         * @return wave
         */
        private float calculateTri(float originalTime, float currentTime) {
            if (progress < PROGRESS / 3) {
                waveHeight = MIN_WAVE_HEIGHT;
            } else if (progress < PROGRESS * 2 / 3) {
                waveHeight = maxWaveHeight;
            } else {
                waveHeight = minWaveHeight;
            }
            return (float) (waveHeight * Math.sin((Math.PI / 80) * (originalTime + currentTime)));
        }
    
        private float convert(float original) {
            return radius * original / RADIUS;
        }
    
        @Override
        protected Parcelable onSaveInstanceState() {
            final Bundle bundle = new Bundle();
            bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState());
            bundle.putFloat(X_I, x);
            bundle.putFloat(Y_I, y);
            bundle.putFloat(RADIUS_I, radius);
            bundle.putFloat(MAX_WAVE_HEIGHT_I, maxWaveHeight);
            bundle.putFloat(MIN_WAVE_HEIGHT_I, minWaveHeight);
            bundle.putFloat(TEXT_Y_I, textY);
            bundle.putFloat(STEP_I, step);
            bundle.putFloat(ELASTICITY_STEP_I, elasticityStep);
            bundle.putFloat(ROPE_STEP_X_I, ropeStepX);
            bundle.putFloat(ROPE_STEP_Y_I, ropeStepY);
            bundle.putFloat(ROPE_HEAD_STEP_Y_I, ropeHeadStepY);
            bundle.putFloat(JUMP_STEP_I, jumpStep);
            bundle.putFloat(DOWN_STEP_I, downStep);
            bundle.putFloat(TRI_STEP_I, triStep);
            bundle.putFloat(HOOK_STEP_Y_I, hookStepY);
            bundle.putFloat(LITTLE_STEP_I, littleStep);
            bundle.putFloat(SMALL_RADIUS_I, smallRadius);
            bundle.putFloat(TEXT_SIZE_I, textSize);
            bundle.putFloat(ARC_WIDTH_I, arcWidth);
            bundle.putFloat(ARROW_WIDTH_I, arrowWidth);
            bundle.putFloat(TRI_WIDTH_I, triWidth);
            bundle.putFloat(LOADING_WIDTH_I, loadingWidth);
            bundle.putBoolean(IS_FIRST_I, isFirst);
            bundle.putBoolean(IS_ANIMATING_I, isAnimating);
            bundle.putBoolean(BEZIER_I, bezier);
            bundle.putBoolean(IS_LOADING_I, isLoading);
            bundle.putBoolean(IS_COMPLETED_I, isCompleted);
            bundle.putBoolean(IS_END_I, isEnd);
            bundle.putInt(COUNT_I, count);
            bundle.putFloat(LENGTH_I, length);
            bundle.putInt(CURRENT_TIME_I, currentTime);
            bundle.putFloat(WAVE_HEIGHT_I, waveHeight);
            bundle.putFloat(PROGRESS_I, progress);
            bundle.putInt(HOOK_COUNT_I, hookCount);
            bundle.putFloat(LENGTH_X_I, lengthX);
            bundle.putFloat(LENGTH_Y_I, lengthY);
            return bundle;
        }
    
        @Override
        protected void onRestoreInstanceState(Parcelable state) {
            if (state instanceof Bundle) {
                final Bundle bundle = (Bundle) state;
                x = bundle.getFloat(X_I);
                y = bundle.getFloat(Y_I);
                radius = bundle.getFloat(RADIUS_I);
                maxWaveHeight = bundle.getFloat(MAX_WAVE_HEIGHT_I);
                minWaveHeight = bundle.getFloat(MIN_WAVE_HEIGHT_I);
                textY = bundle.getFloat(TEXT_Y_I);
                step = bundle.getFloat(STEP_I);
                elasticityStep = bundle.getFloat(ELASTICITY_STEP_I);
                ropeStepX = bundle.getFloat(ROPE_STEP_X_I);
                ropeStepY = bundle.getFloat(ROPE_STEP_Y_I);
                ropeHeadStepY = bundle.getFloat(ROPE_HEAD_STEP_Y_I);
                jumpStep = bundle.getFloat(JUMP_STEP_I);
                downStep = bundle.getFloat(DOWN_STEP_I);
                triStep = bundle.getFloat(TRI_STEP_I);
                hookStepY = bundle.getFloat(HOOK_STEP_Y_I);
                littleStep = bundle.getFloat(LITTLE_STEP_I);
                smallRadius = bundle.getFloat(SMALL_RADIUS_I);
                textSize = bundle.getFloat(TEXT_SIZE_I);
                arcWidth = bundle.getFloat(ARC_WIDTH_I);
                arrowWidth = bundle.getFloat(ARROW_WIDTH_I);
                triWidth = bundle.getFloat(TRI_WIDTH_I);
                loadingWidth = bundle.getFloat(LOADING_WIDTH_I);
                isFirst = bundle.getBoolean(IS_FIRST_I);
                isAnimating = bundle.getBoolean(IS_ANIMATING_I);
                bezier = bundle.getBoolean(BEZIER_I);
                isLoading = bundle.getBoolean(IS_LOADING_I);
                isCompleted = bundle.getBoolean(IS_COMPLETED_I);
                isEnd = bundle.getBoolean(IS_END_I);
                count = bundle.getInt(COUNT_I);
                length = bundle.getFloat(LENGTH_I);
                currentTime = bundle.getInt(CURRENT_TIME_I);
                waveHeight = bundle.getFloat(WAVE_HEIGHT_I);
                progress = bundle.getFloat(PROGRESS_I);
                hookCount = bundle.getInt(HOOK_COUNT_I);
                lengthX = bundle.getFloat(LENGTH_X_I);
                lengthY = bundle.getFloat(LENGTH_Y_I);
            }
            super.onRestoreInstanceState(state);
        }
    
        static class Point {
            public float x;
            public float y;
    
            public Point(float x, float y) {
                this.x = x;
                this.y = y;
            }
    
            public Point() {
                x = -1;
                y = -1;
            }
        }
    }
    
    

    相关文章

      网友评论

          本文标题:加载中Loading ArrowDownloadButton

          本文链接:https://www.haomeiwen.com/subject/ghtuahtx.html