美文网首页
下载进度按钮

下载进度按钮

作者: 菜鸟何时起飞 | 来源:发表于2020-05-25 23:23 被阅读0次
    687474703a2f2f7777342e73696e61696d672e636e2f6c617267652f303036306c6d37546777316578317972326239786a6a3330656730676f37356e2e6a7067.jpeg
    public class AnimDownloadProgressButton extends AppCompatTextView {
    
        private Context mContext;
    
        //背景画笔
        private Paint mBackgroundPaint;
        //按钮文字画笔
        private volatile Paint mTextPaint;
        //第一个点画笔
        private Paint mDot1Paint;
        //第二个点画笔
        private Paint mDot2Paint;
    
    
        //背景颜色
        private int[] mBackgroundColor;
        private int[] mOriginBackgroundColor;
        //下载中后半部分后面背景颜色
        private int mBackgroundSecondColor;
        //文字颜色
        private int mTextColor;
        //覆盖后颜色
        private int mTextCoverColor;
        //文字大小
        private float mAboveTextSize = 50;
    
    
        private float mProgress = -1;
        private float mToProgress;
        private int mMaxProgress;
        private int mMinProgress;
        private float mProgressPercent;
    
        private float mButtonRadius;
    
        //两个点向右移动距离
        private float mDot1transX;
        private float mDot2transX;
    
        private RectF mBackgroundBounds;
        private LinearGradient mFillBgGradient;
        private LinearGradient mProgressBgGradient;
        private LinearGradient mProgressTextGradient;
    
        //点运动动画
        private AnimatorSet mDotAnimationSet;
        //下载平滑动画
        private ValueAnimator mProgressAnimation;
    
        //记录当前文字
        private CharSequence mCurrentText;
    
        //普通状态
        public static final int NORMAL = 0;
        //下载中
        public static final int DOWNLOADING = 1;
        //有点运动状态
        public static final int INSTALLING = 2;
    
        private ButtonController mDefaultController;
    
        private ButtonController mCustomerController;
    
    
        private int mState;
    
        public AnimDownloadProgressButton(Context context) {
            this(context, null);
    
        }
    
        public AnimDownloadProgressButton(Context context, AttributeSet attrs) {
            super(context, attrs);
            if (!isInEditMode()) {
                mContext = context;
                initController();
                initAttrs(context, attrs);
                init();
                setupAnimations();
            } else {
                initController();
            }
    
        }
    
        private void initController() {
            mDefaultController = new DefaultButtonController();
        }
    
        @Override
        protected void drawableStateChanged() {
            super.drawableStateChanged();
            ButtonController buttonController = switchController();
            if (buttonController.enablePress()) {
                if (mOriginBackgroundColor == null) {
                    mOriginBackgroundColor = new int[2];
                    mOriginBackgroundColor[0] = mBackgroundColor[0];
                    mOriginBackgroundColor[1] = mBackgroundColor[1];
                }
                if (this.isPressed()) {
                    int pressColorleft = buttonController.getPressedColor(mBackgroundColor[0]);
                    int pressColorright = buttonController.getPressedColor(mBackgroundColor[1]);
                    if (buttonController.enableGradient()) {
                        initGradientColor(pressColorleft, pressColorright);
                    } else {
                        initGradientColor(pressColorleft, pressColorleft);
                    }
                } else {
                    if (buttonController.enableGradient()) {
                        initGradientColor(mOriginBackgroundColor[0], mOriginBackgroundColor[1]);
                    } else {
                        initGradientColor(mOriginBackgroundColor[0], mOriginBackgroundColor[0]);
                    }
                }
                invalidate();
            }
    
        }
    
        private void initAttrs(Context context, AttributeSet attrs) {
    
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AnimDownloadProgressButton);
            int bgColor = a.getColor(R.styleable.AnimDownloadProgressButton_progressbtn_background_color, Color.parseColor("#6699ff"));
            //初始化背景颜色数组
            initGradientColor(bgColor, bgColor);
            mBackgroundSecondColor = a.getColor(R.styleable.AnimDownloadProgressButton_progressbtn_background_second_color, Color.LTGRAY);
            mButtonRadius = a.getFloat(R.styleable.AnimDownloadProgressButton_progressbtn_radius, getMeasuredHeight() / 2);
            mAboveTextSize = a.getFloat(R.styleable.AnimDownloadProgressButton_progressbtn_text_size, 50);
            mTextColor = a.getColor(R.styleable.AnimDownloadProgressButton_progressbtn_text_color, bgColor);
            mTextCoverColor = a.getColor(R.styleable.AnimDownloadProgressButton_progressbtn_text_covercolor, Color.WHITE);
            boolean enableGradient = a.getBoolean(R.styleable.AnimDownloadProgressButton_progressbtn_enable_gradient, false);
            boolean enablePress = a.getBoolean(R.styleable.AnimDownloadProgressButton_progressbtn_enable_press, false);
            ((DefaultButtonController) mDefaultController).setEnableGradient(enableGradient).setEnablePress(enablePress);
            if (enableGradient) {
                initGradientColor(mDefaultController.getLighterColor(mBackgroundColor[0]), mBackgroundColor[0]);
            }
            a.recycle();
        }
    
        private void init() {
    
            mMaxProgress = 100;
            mMinProgress = 0;
            mProgress = 0;
    
    
            //设置背景画笔
            mBackgroundPaint = new Paint();
            mBackgroundPaint.setAntiAlias(true);
            mBackgroundPaint.setStyle(Paint.Style.FILL);
    
            //设置文字画笔
            mTextPaint = new Paint();
            mTextPaint.setAntiAlias(true);
            mTextPaint.setTextSize(mAboveTextSize);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                //解决文字有时候画不出问题
                setLayerType(LAYER_TYPE_SOFTWARE, mTextPaint);
            }
    
            //设置第一个点画笔
            mDot1Paint = new Paint();
            mDot1Paint.setAntiAlias(true);
            mDot1Paint.setTextSize(mAboveTextSize);
    
            //设置第二个点画笔
            mDot2Paint = new Paint();
            mDot2Paint.setAntiAlias(true);
            mDot2Paint.setTextSize(mAboveTextSize);
    
    
            //初始化状态设为NORMAL
            mState = NORMAL;
            invalidate();
    
        }
    
        //初始化渐变色
        private int[] initGradientColor(int leftColor, int rightColor) {
            mBackgroundColor = new int[2];
            mBackgroundColor[0] = leftColor;
            mBackgroundColor[1] = rightColor;
            return mBackgroundColor;
        }
    
    
        private void setupAnimations() {
    
            //两个点向右移动动画
            ValueAnimator dotMoveAnimation = ValueAnimator.ofFloat(0, 20);
            TimeInterpolator pathInterpolator = PathInterpolatorCompat.create(0.11f, 0f, 0.12f, 1f);
            dotMoveAnimation.setInterpolator(pathInterpolator);
            dotMoveAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float transX = (float) animation.getAnimatedValue();
                    mDot1transX = transX;
                    mDot2transX = transX;
                    invalidate();
                }
            });
            dotMoveAnimation.setDuration(1243);
            dotMoveAnimation.setRepeatMode(ValueAnimator.RESTART);
            dotMoveAnimation.setRepeatCount(ValueAnimator.INFINITE);
    
    
            //两个点渐显渐隐动画
            final ValueAnimator dotAlphaAnim = ValueAnimator.ofInt(0, 1243).setDuration(1243);
            dotAlphaAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    int time = (int) dotAlphaAnim.getAnimatedValue();
                    int dot1Alpha = calculateDot1AlphaByTime(time);
                    int dot2Alpha = calculateDot2AlphaByTime(time);
                    mDot1Paint.setColor(mTextCoverColor);
                    mDot2Paint.setColor(mTextCoverColor);
                    mDot1Paint.setAlpha(dot1Alpha);
                    mDot2Paint.setAlpha(dot2Alpha);
                }
    
            });
    
    
            dotAlphaAnim.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                    mDot1Paint.setAlpha(0);
                    mDot2Paint.setAlpha(0);
                }
    
                @Override
                public void onAnimationEnd(Animator animation) {
                }
    
                @Override
                public void onAnimationCancel(Animator animation) {
    
                }
    
                @Override
                public void onAnimationRepeat(Animator animation) {
    
                }
            });
            dotAlphaAnim.setRepeatMode(ValueAnimator.RESTART);
            dotAlphaAnim.setRepeatCount(ValueAnimator.INFINITE);
            //两个点的动画集合
            mDotAnimationSet = new AnimatorSet();
            mDotAnimationSet.playTogether(dotAlphaAnim, dotMoveAnimation);
    
            //ProgressBar的动画
            mProgressAnimation = ValueAnimator.ofFloat(0, 1).setDuration(500);
            mProgressAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float timepercent = (float) animation.getAnimatedValue();
                    mProgress = ((mToProgress - mProgress) * timepercent + mProgress);
                    invalidate();
                }
            });
    
    
        }
    
        //第一个点透明度计算函数
        private int calculateDot2AlphaByTime(int time) {
            int alpha;
            if (0 <= time && time <= 83) {
                double DAlpha = 255.0 / 83.0 * time;
                alpha = (int) DAlpha;
            } else if (83 < time && time <= 1000) {
                alpha = 255;
            } else if (1000 < time && time <= 1083) {
                double DAlpha = -255.0 / 83.0 * (time - 1083);
                alpha = (int) DAlpha;
            } else if (1083 < time && time <= 1243) {
                alpha = 0;
            } else {
                alpha = 255;
            }
            return alpha;
        }
    
        //第二个点透明度计算函数
        private int calculateDot1AlphaByTime(int time) {
            int alpha;
            if (0 <= time && time <= 160) {
                alpha = 0;
            } else if (160 < time && time <= 243) {
                double DAlpha = 255.0 / 83.0 * (time - 160);
                alpha = (int) DAlpha;
            } else if (243 < time && time <= 1160) {
                alpha = 255;
            } else if (1160 < time && time <= 1243) {
                double DAlpha = -255.0 / 83.0 * (time - 1243);
                alpha = (int) DAlpha;
            } else {
                alpha = 255;
            }
            return alpha;
        }
    
    
        private ValueAnimator createDotAlphaAnimation(int i, Paint mDot1Paint, int i1, int i2, int i3) {
    
            return new ValueAnimator();
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            if (!isInEditMode()) {
                drawing(canvas);
            }
        }
    
        private void drawing(Canvas canvas) {
            drawBackground(canvas);
            drawTextAbove(canvas);
        }
    
        private void drawBackground(Canvas canvas) {
            mBackgroundBounds = new RectF();
            if (mButtonRadius == 0) {
                mButtonRadius = getMeasuredHeight() / 2;
            }
            mBackgroundBounds.left = 2;
            mBackgroundBounds.top = 2;
            mBackgroundBounds.right = getMeasuredWidth() - 2;
            mBackgroundBounds.bottom = getMeasuredHeight() - 2;
    
            ButtonController buttonController = switchController();
    
            //color
            switch (mState) {
                case NORMAL:
                    if (buttonController.enableGradient()) {
                        mFillBgGradient = new LinearGradient(0, getMeasuredHeight() / 2, getMeasuredWidth(), getMeasuredHeight() / 2,
                                mBackgroundColor,
                                null,
                                Shader.TileMode.CLAMP);
                        mBackgroundPaint.setShader(mFillBgGradient);
                    } else {
                        if (mBackgroundPaint.getShader() != null) {
                            mBackgroundPaint.setShader(null);
                        }
                        mBackgroundPaint.setColor(mBackgroundColor[0]);
                    }
                    canvas.drawRoundRect(mBackgroundBounds, mButtonRadius, mButtonRadius, mBackgroundPaint);
                    break;
                case DOWNLOADING:
                    if (buttonController.enableGradient()) {
                        mProgressPercent = mProgress / (mMaxProgress + 0f);
                        int[] colorList = new int[]{mBackgroundColor[0], mBackgroundColor[1], mBackgroundSecondColor};
                        mProgressBgGradient = new LinearGradient(0, 0, getMeasuredWidth(), 0,
                                colorList,
                                new float[]{0, mProgressPercent, mProgressPercent + 0.001f},
                                Shader.TileMode.CLAMP
                        );
                        mBackgroundPaint.setShader(mProgressBgGradient);
                    } else {
                        mProgressPercent = mProgress / (mMaxProgress + 0f);
                        mProgressBgGradient = new LinearGradient(0, 0, getMeasuredWidth(), 0,
                                new int[]{mBackgroundColor[0], mBackgroundSecondColor},
                                new float[]{mProgressPercent, mProgressPercent + 0.001f},
                                Shader.TileMode.CLAMP
                        );
                        mBackgroundPaint.setColor(mBackgroundColor[0]);
                        mBackgroundPaint.setShader(mProgressBgGradient);
                    }
                    canvas.drawRoundRect(mBackgroundBounds, mButtonRadius, mButtonRadius, mBackgroundPaint);
                    break;
                case INSTALLING:
                    if (buttonController.enableGradient()) {
                        mFillBgGradient = new LinearGradient(0, getMeasuredHeight() / 2, getMeasuredWidth(), getMeasuredHeight() / 2,
                                mBackgroundColor,
                                null,
                                Shader.TileMode.CLAMP);
                        mBackgroundPaint.setShader(mFillBgGradient);
                    } else {
                        mBackgroundPaint.setShader(null);
                        mBackgroundPaint.setColor(mBackgroundColor[0]);
                    }
                    canvas.drawRoundRect(mBackgroundBounds, mButtonRadius, mButtonRadius, mBackgroundPaint);
                    break;
            }
        }
    
        private void drawTextAbove(Canvas canvas) {
            final float y = canvas.getHeight() / 2 - (mTextPaint.descent() / 2 + mTextPaint.ascent() / 2);
            if (mCurrentText == null) {
                mCurrentText = "";
            }
            final float textWidth = mTextPaint.measureText(mCurrentText.toString());
            //color
            switch (mState) {
                case NORMAL:
                    mTextPaint.setShader(null);
                    mTextPaint.setColor(mTextCoverColor);
                    canvas.drawText(mCurrentText.toString(), (getMeasuredWidth() - textWidth) / 2, y, mTextPaint);
                    break;
                case DOWNLOADING:
    
                    //进度条压过距离
                    float coverlength = getMeasuredWidth() * mProgressPercent;
                    //开始渐变指示器
                    float indicator1 = getMeasuredWidth() / 2 - textWidth / 2;
                    //结束渐变指示器
                    float indicator2 = getMeasuredWidth() / 2 + textWidth / 2;
                    //文字变色部分的距离
                    float coverTextLength = textWidth / 2 - getMeasuredWidth() / 2 + coverlength;
                    float textProgress = coverTextLength / textWidth;
                    if (coverlength <= indicator1) {
                        mTextPaint.setShader(null);
                        mTextPaint.setColor(mTextColor);
                    } else if (indicator1 < coverlength && coverlength <= indicator2) {
                       /*左右各一个颜色*/
                        mProgressTextGradient = new LinearGradient((getMeasuredWidth() - textWidth) / 2, 0, (getMeasuredWidth() + textWidth) / 2, 0,
                                new int[]{mTextCoverColor, mTextColor},
                                new float[]{textProgress, textProgress + 0.001f},
                                Shader.TileMode.CLAMP);
                        mTextPaint.setColor(mTextColor);
                        mTextPaint.setShader(mProgressTextGradient);
                    } else {
                        mTextPaint.setShader(null);
                        mTextPaint.setColor(mTextCoverColor);
                    }
                    canvas.drawText(mCurrentText.toString(), (getMeasuredWidth() - textWidth) / 2, y, mTextPaint);
                    break;
                case INSTALLING:
                    mTextPaint.setColor(mTextCoverColor);
                    canvas.drawText(mCurrentText.toString(), (getMeasuredWidth() - textWidth) / 2, y, mTextPaint);
                    canvas.drawCircle((getMeasuredWidth() + textWidth) / 2 + 4 + mDot1transX, y, 4, mDot1Paint);
                    canvas.drawCircle((getMeasuredWidth() + textWidth) / 2 + 24 + mDot2transX, y, 4, mDot2Paint);
                    break;
    
            }
    
        }
    
        private ButtonController switchController() {
            if (mCustomerController != null) {
                return mCustomerController;
            } else {
                return mDefaultController;
            }
        }
    
        public int getState() {
            return mState;
        }
    
        public void setState(int state) {
            if (mState != state) {//状态确实有改变
                this.mState = state;
                invalidate();
                if (state == AnimDownloadProgressButton.INSTALLING) {
                    //开启两个点动画
                    mDotAnimationSet.start();
                } else if (state == NORMAL) {
                    mDotAnimationSet.cancel();
                } else if (state == DOWNLOADING) {
                    mDotAnimationSet.cancel();
                }
            }
    
        }
    
        /**
         * 设置按钮文字
         */
        public void setCurrentText(CharSequence charSequence) {
            mCurrentText = charSequence;
            invalidate();
        }
    
    
        /**
         * 设置带下载进度的文字
         */
        @TargetApi(Build.VERSION_CODES.KITKAT)
        public void setProgressText(String text, float progress) {
            if (progress >= mMinProgress && progress < mMaxProgress) {
                mCurrentText = text + "="+progress;
                mToProgress = progress;
                if (mProgressAnimation.isRunning()) {
                    mProgressAnimation.start();
                } else {
                    mProgressAnimation.start();
                }
            } else if (progress < mMinProgress) {
                mProgress = 0;
            } else if (progress >= mMaxProgress) {
                mProgress = 100;
                mCurrentText = text + "="+progress;
                invalidate();
            }
        }
    
        public float getProgress() {
            return mProgress;
        }
    
        public void setProgress(float progress) {
            this.mProgress = progress;
    
        }
    
        /**
         * Sometimes you should use the method to avoid memory leak
         */
        public void removeAllAnim() {
            mDotAnimationSet.cancel();
            mDotAnimationSet.removeAllListeners();
            mProgressAnimation.cancel();
            mProgressAnimation.removeAllListeners();
        }
    
    
        public void setProgressBtnBackgroundColor(int color) {
            initGradientColor(color, color);
        }
    
    
        public void setProgressBtnBackgroundSecondColor(int color) {
    
            mBackgroundSecondColor = color;
        }
    
        public float getButtonRadius() {
            return mButtonRadius;
        }
    
        public void setButtonRadius(float buttonRadius) {
            mButtonRadius = buttonRadius;
        }
    
        public int getTextColor() {
            return mTextColor;
        }
    
        @Override
        public void setTextColor(int textColor) {
            mTextColor = textColor;
        }
    
        public int getTextCoverColor() {
            return mTextCoverColor;
        }
    
        public void setTextCoverColor(int textCoverColor) {
            mTextCoverColor = textCoverColor;
        }
    
        public int getMinProgress() {
            return mMinProgress;
        }
    
        public void setMinProgress(int minProgress) {
            mMinProgress = minProgress;
        }
    
        public int getMaxProgress() {
            return mMaxProgress;
        }
    
        public void setMaxProgress(int maxProgress) {
            mMaxProgress = maxProgress;
        }
    
        public void enabelDefaultPress(boolean enable) {
            if (mDefaultController != null) {
                ((DefaultButtonController) mDefaultController).setEnablePress(enable);
            }
        }
    
        public void enabelDefaultGradient(boolean enable) {
            if (mDefaultController != null) {
                ((DefaultButtonController) mDefaultController).setEnableGradient(enable);
                initGradientColor(mDefaultController.getLighterColor(mBackgroundColor[0]), mBackgroundColor[0]);
            }
        }
    
        @Override
        public void setTextSize(float size) {
            mAboveTextSize = size;
            mTextPaint.setTextSize(size);
        }
    
        @Override
        public float getTextSize() {
            return mAboveTextSize;
        }
    
        public AnimDownloadProgressButton setCustomerController(ButtonController customerController) {
            mCustomerController = customerController;
            return this;
        }
    
        @Override
        public void onRestoreInstanceState(Parcelable state) {
            SavedState ss = (SavedState) state;
            super.onRestoreInstanceState(ss.getSuperState());
            mState = ss.state;
            mProgress = ss.progress;
            mCurrentText = ss.currentText;
        }
    
        @Override
        public Parcelable onSaveInstanceState() {
            Parcelable superState = super.onSaveInstanceState();
            return new SavedState(superState, (int) mProgress, mState, mCurrentText.toString());
        }
    
        public static class SavedState extends BaseSavedState {
    
            private int progress;
            private int state;
            private String currentText;
    
            public SavedState(Parcelable parcel, int progress, int state, String currentText) {
                super(parcel);
                this.progress = progress;
                this.state = state;
                this.currentText = currentText;
            }
    
            private SavedState(Parcel in) {
                super(in);
                progress = in.readInt();
                state = in.readInt();
                currentText = in.readString();
            }
    
            @Override
            public void writeToParcel(Parcel out, int flags) {
                super.writeToParcel(out, flags);
                out.writeInt(progress);
                out.writeInt(state);
                out.writeString(currentText);
            }
    
            public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
    
                @Override
                public SavedState createFromParcel(Parcel in) {
                    return new SavedState(in);
                }
    
                @Override
                public SavedState[] newArray(int size) {
                    return new SavedState[size];
                }
            };
    
        }
    
    
    }
    
    public interface ButtonController {
        int getPressedColor(int color);
    
        int getLighterColor(int color);
    
        int getDarkerColor(int color);
    
        boolean enablePress();
    
        boolean enableGradient();
    
    }
    
    public class DefaultButtonController implements ButtonController {
    
    
        private boolean enablePress;
    
        private boolean enableGradient;
    
        /**
         * 获得按下的颜色(明度降低10%)
         *
         * @param color
         * @return int
         */
        public int getPressedColor(int color) {
            float[] hsv = new float[3];
            Color.colorToHSV(color, hsv);
            hsv[2] -= 0.1f;
            return Color.HSVToColor(hsv);
        }
    
        /**
         * 由右边的颜色算出左边的颜色(左边的颜色比右边的颜色降饱和度30%,亮度增加30%)
         * +
         *
         * @param color
         * @return
         */
        public int getLighterColor(int color) {
            float[] hsv = new float[3];
            Color.colorToHSV(color, hsv);
            hsv[1] -= 0.3f;
            hsv[2] += 0.3f;
            return Color.HSVToColor(hsv);
        }
    
        /**
         * 由左边的颜色生成右边的颜色
         *
         * @param color
         * @return int
         */
        public int getDarkerColor(int color) {
            float[] hsv = new float[3];
            Color.colorToHSV(color, hsv);
            hsv[1] += 0.3f;
            hsv[2] -= 0.3f;
            return Color.HSVToColor(hsv);
        }
    
        @Override
        public boolean enablePress() {
            return enablePress;
        }
    
        @Override
        public boolean enableGradient() {
            return enableGradient;
        }
    
        public DefaultButtonController setEnablePress(boolean enablePress) {
            this.enablePress = enablePress;
            return this;
        }
    
        public DefaultButtonController setEnableGradient(boolean enableGradient) {
            this.enableGradient = enableGradient;
            return this;
        }
    }
    
    

    相关文章

      网友评论

          本文标题:下载进度按钮

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