美文网首页
购物车按钮

购物车按钮

作者: 菜鸟何时起飞 | 来源:发表于2020-05-25 17:41 被阅读0次
    testAttr.gif
    public class AnimShopButton extends View {
        protected static final String TAG = "zxt/" + AnimShopButton.class.getName();
        protected static final int DEFAULT_DURATION = 350;
        //控件 paddingLeft paddingTop + paint的width
        protected int mLeft, mTop;
        //宽高
        protected int mWidth, mHeight;
    
    
        //加减的圆的Path的Region
        protected Region mAddRegion, mDelRegion;
        protected Path mAddPath, mDelPath;
    
        /**
         * 加按钮
         */
        protected Paint mAddPaint;
        //加按钮是否开启fill模式 默认是stroke(xml)(false)
        protected boolean isAddFillMode;
        //加按钮的背景色前景色(xml)
        protected int mAddEnableBgColor;
        protected int mAddEnableFgColor;
        //加按钮不可用时的背景色前景色(xml)
        protected int mAddDisableBgColor;
        protected int mAddDisableFgColor;
    
        /**
         * 减按钮
         */
        protected Paint mDelPaint;
        //按钮是否开启fill模式 默认是stroke(xml)(false)
        protected boolean isDelFillMode;
        //按钮的背景色前景色(xml)
        protected int mDelEnableBgColor;
        protected int mDelEnableFgColor;
        //按钮不可用时的背景色前景色(xml)
        protected int mDelDisableBgColor;
        protected int mDelDisableFgColor;
    
        //最大数量和当前数量(xml)
        protected int mMaxCount;
        protected int mCount;
    
        //圆的半径
        protected float mRadius;
        //圆圈的宽度
        protected float mCircleWidth;
        //线的宽度
        protected float mLineWidth;
    
    
        /**
         * 两个圆之间的间距(xml)
         */
        protected float mGapBetweenCircle;
        //绘制数量的textSize
        protected float mTextSize;
        protected Paint mTextPaint;
        protected Paint.FontMetrics mFontMetrics;
    
        //动画的基准值 动画:减 0~1, 加 1~0 ,
        // 普通状态下都显示时是0
        protected ValueAnimator mAnimAdd, mAniDel;
        protected float mAnimFraction;
    
        //展开 加入购物车动画
        protected ValueAnimator mAnimExpandHint;
        protected ValueAnimator mAnimReduceHint;
    
        protected int mPerAnimDuration = DEFAULT_DURATION;
    
        /**
         * 增加一个开关 ignoreHintArea:UI显示、动画是否忽略hint收缩区域
         */
        protected boolean ignoreHintArea;
    
        //是否处于HintMode下 count = 0 时,且第一段收缩动画做完了,是true
        protected boolean isHintMode;
    
        //提示语收缩动画 0-1 展开1-0
        //普通模式时,应该是1, 只在 isHintMode true 才有效
        protected float mAnimExpandHintFraction;
    
        //展开动画结束后 才显示文字
        protected boolean isShowHintText;
    
        //数量为0时,hint文字 背景色前景色(xml) 大小
        protected Paint mHintPaint;
        protected int mHintBgColor;
        protected int mHingTextSize;
        protected String mHintText;
        protected int mHintFgColor;
        /**
         * 圆角值(xml)
         */
        protected int mHintBgRoundValue;
    
        //Feature : 显示正在补货中,此时不允许点击
        protected boolean isReplenish;
        //画笔、颜色、大小、文字
        protected Paint mReplenishPaint;
        protected int mReplenishTextColor;
        protected int mReplenishTextSize;
        protected String mReplenishText;
    
    
        //点击回调
        protected IOnAddDelListener mOnAddDelListener;
    
        public AnimShopButton(Context context) {
            this(context, null);
        }
    
        public AnimShopButton(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public AnimShopButton(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context, attrs, defStyleAttr);
        }
    
        public int getCount() {
            return mCount;
        }
    
        /**
         * 设置当前数量
         *
         * @param count
         * @return
         */
        public AnimShopButton setCount(int count) {
            mCount = count;
            //先暂停所有动画
            cancelAllAnim();
    
            //复用机制的处理
    
            initAnimSettingsByCount();
            return this;
        }
    
        /**
         * 暂停所有动画
         */
        private void cancelAllAnim() {
            if (mAnimAdd != null && mAnimAdd.isRunning()) {
                mAnimAdd.cancel();
            }
            if (mAniDel != null && mAniDel.isRunning()) {
                mAniDel.cancel();
            }
            if (mAnimExpandHint != null && mAnimExpandHint.isRunning()) {
                mAnimExpandHint.cancel();
            }
            if (mAnimReduceHint != null && mAnimReduceHint.isRunning()) {
                mAnimReduceHint.cancel();
            }
        }
    
        public IOnAddDelListener getOnAddDelListener() {
            return mOnAddDelListener;
        }
    
        public int getMaxCount() {
            return mMaxCount;
        }
    
        /**
         * 设置最大数量
         *
         * @param maxCount
         * @return
         */
        public AnimShopButton setMaxCount(int maxCount) {
            mMaxCount = maxCount;
            return this;
        }
    
        public boolean isReplenish() {
            return isReplenish;
        }
    
        public AnimShopButton setReplenish(boolean replenish) {
            isReplenish = replenish;
            if (isReplenish && null == mReplenishPaint) {
                mReplenishPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
                mReplenishPaint.setTextSize(mReplenishTextSize);
                mReplenishPaint.setColor(mReplenishTextColor);
            }
            return this;
        }
    
        public int getReplenishTextColor() {
            return mReplenishTextColor;
        }
    
        public AnimShopButton setReplenishTextColor(int replenishTextColor) {
            mReplenishTextColor = replenishTextColor;
            return this;
        }
    
        public int getReplenishTextSize() {
            return mReplenishTextSize;
        }
    
        public AnimShopButton setReplenishTextSize(int replenishTextSize) {
            mReplenishTextSize = replenishTextSize;
            return this;
        }
    
        public String getReplenishText() {
            return mReplenishText;
        }
    
        public AnimShopButton setReplenishText(String replenishText) {
            mReplenishText = replenishText;
            return this;
        }
    
        public boolean isAddFillMode() {
            return isAddFillMode;
        }
    
        public AnimShopButton setAddFillMode(boolean addFillMode) {
            isAddFillMode = addFillMode;
            return this;
        }
    
        public int getAddEnableBgColor() {
            return mAddEnableBgColor;
        }
    
        public AnimShopButton setAddEnableBgColor(int addEnableBgColor) {
            mAddEnableBgColor = addEnableBgColor;
            return this;
        }
    
        public int getAddEnableFgColor() {
            return mAddEnableFgColor;
        }
    
        public AnimShopButton setAddEnableFgColor(int addEnableFgColor) {
            mAddEnableFgColor = addEnableFgColor;
            return this;
        }
    
        public int getAddDisableBgColor() {
            return mAddDisableBgColor;
        }
    
        public AnimShopButton setAddDisableBgColor(int addDisableBgColor) {
            mAddDisableBgColor = addDisableBgColor;
            return this;
        }
    
        public int getAddDisableFgColor() {
            return mAddDisableFgColor;
        }
    
        public AnimShopButton setAddDisableFgColor(int addDisableFgColor) {
            mAddDisableFgColor = addDisableFgColor;
            return this;
        }
    
        public boolean isDelFillMode() {
            return isDelFillMode;
        }
    
        public AnimShopButton setDelFillMode(boolean delFillMode) {
            isDelFillMode = delFillMode;
            return this;
        }
    
        public int getDelEnableBgColor() {
            return mDelEnableBgColor;
        }
    
        public AnimShopButton setDelEnableBgColor(int delEnableBgColor) {
            mDelEnableBgColor = delEnableBgColor;
            return this;
        }
    
        public int getDelEnableFgColor() {
            return mDelEnableFgColor;
        }
    
        public AnimShopButton setDelEnableFgColor(int delEnableFgColor) {
            mDelEnableFgColor = delEnableFgColor;
            return this;
        }
    
        public int getDelDisableBgColor() {
            return mDelDisableBgColor;
        }
    
        public AnimShopButton setDelDisableBgColor(int delDisableBgColor) {
            mDelDisableBgColor = delDisableBgColor;
            return this;
        }
    
        public int getDelDisableFgColor() {
            return mDelDisableFgColor;
        }
    
        public AnimShopButton setDelDisableFgColor(int delDisableFgColor) {
            mDelDisableFgColor = delDisableFgColor;
            return this;
        }
    
        public float getRadius() {
            return mRadius;
        }
    
        public AnimShopButton setRadius(float radius) {
            mRadius = radius;
            return this;
        }
    
        public float getCircleWidth() {
            return mCircleWidth;
        }
    
        public AnimShopButton setCircleWidth(float circleWidth) {
            mCircleWidth = circleWidth;
            return this;
        }
    
        public float getLineWidth() {
            return mLineWidth;
        }
    
        public AnimShopButton setLineWidth(float lineWidth) {
            mLineWidth = lineWidth;
            return this;
        }
    
        public float getTextSize() {
            return mTextSize;
        }
    
        public AnimShopButton setTextSize(float textSize) {
            mTextSize = textSize;
            return this;
        }
    
        public float getGapBetweenCircle() {
            return mGapBetweenCircle;
        }
    
        public AnimShopButton setGapBetweenCircle(float gapBetweenCircle) {
            mGapBetweenCircle = gapBetweenCircle;
            return this;
        }
    
        public int getPerAnimDuration() {
            return mPerAnimDuration;
        }
    
        public AnimShopButton setPerAnimDuration(int perAnimDuration) {
            mPerAnimDuration = perAnimDuration;
            return this;
        }
    
        public boolean isIgnoreHintArea() {
            return ignoreHintArea;
        }
    
        public AnimShopButton setIgnoreHintArea(boolean ignoreHintArea) {
            this.ignoreHintArea = ignoreHintArea;
            return this;
        }
    
        public int getHintBgColor() {
            return mHintBgColor;
        }
    
        public AnimShopButton setHintBgColor(int hintBgColor) {
            mHintBgColor = hintBgColor;
            return this;
        }
    
        public int getHingTextSize() {
            return mHingTextSize;
        }
    
        public AnimShopButton setHingTextSize(int hingTextSize) {
            mHingTextSize = hingTextSize;
            return this;
        }
    
        public String getHintText() {
            return mHintText;
        }
    
        public AnimShopButton setHintText(String hintText) {
            mHintText = hintText;
            return this;
        }
    
        public int getHintFgColor() {
            return mHintFgColor;
        }
    
        public AnimShopButton setHintFgColor(int hintFgColor) {
            mHintFgColor = hintFgColor;
            return this;
        }
    
        public int getHintBgRoundValue() {
            return mHintBgRoundValue;
        }
    
        public AnimShopButton setHintBgRoundValue(int hintBgRoundValue) {
            mHintBgRoundValue = hintBgRoundValue;
            return this;
        }
    
        /**
         * 设置加减监听器
         *
         * @param IOnAddDelListener
         * @return
         */
        public AnimShopButton setOnAddDelListener(IOnAddDelListener IOnAddDelListener) {
            mOnAddDelListener = IOnAddDelListener;
            return this;
        }
    
        protected void init(Context context, AttributeSet attrs, int defStyleAttr) {
    
            //模拟参数传入(设置初始值)
            initDefaultValue(context);
            //end
    
            TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.AnimShopButton, defStyleAttr, 0);
            int indexCount = ta.getIndexCount();
            for (int i = 0; i < indexCount; i++) {
                int index = ta.getIndex(i);
                if (index == R.styleable.AnimShopButton_gapBetweenCircle) {
                    mGapBetweenCircle = ta.getDimension(index, mGapBetweenCircle);
                } else if (index == R.styleable.AnimShopButton_isAddFillMode) {
                    isAddFillMode = ta.getBoolean(index, isAddFillMode);
                } else if (index == R.styleable.AnimShopButton_addEnableBgColor) {
                    mAddEnableBgColor = ta.getColor(index, mAddEnableBgColor);
                } else if (index == R.styleable.AnimShopButton_addEnableFgColor) {
                    mAddEnableFgColor = ta.getColor(index, mAddEnableFgColor);
                } else if (index == R.styleable.AnimShopButton_addDisableBgColor) {
                    mAddDisableBgColor = ta.getColor(index, mAddDisableBgColor);
                } else if (index == R.styleable.AnimShopButton_addDisableFgColor) {
                    mAddDisableFgColor = ta.getColor(index, mAddDisableFgColor);
                } else if (index == R.styleable.AnimShopButton_isDelFillMode) {
                    isDelFillMode = ta.getBoolean(index, isDelFillMode);
                } else if (index == R.styleable.AnimShopButton_delEnableBgColor) {
                    mDelEnableBgColor = ta.getColor(index, mDelEnableBgColor);
                } else if (index == R.styleable.AnimShopButton_delEnableFgColor) {
                    mDelEnableFgColor = ta.getColor(index, mDelEnableFgColor);
                } else if (index == R.styleable.AnimShopButton_delDisableBgColor) {
                    mDelDisableBgColor = ta.getColor(index, mDelDisableBgColor);
                } else if (index == R.styleable.AnimShopButton_delDisableFgColor) {
                    mDelDisableFgColor = ta.getColor(index, mDelDisableFgColor);
                } else if (index == R.styleable.AnimShopButton_maxCount) {
                    mMaxCount = ta.getInteger(index, mMaxCount);
                } else if (index == R.styleable.AnimShopButton_count) {
                    mCount = ta.getInteger(index, mCount);
                } else if (index == R.styleable.AnimShopButton_radius) {
                    mRadius = ta.getDimension(index, mRadius);
                } else if (index == R.styleable.AnimShopButton_circleStrokeWidth) {
                    mCircleWidth = ta.getDimension(index, mCircleWidth);
                } else if (index == R.styleable.AnimShopButton_lineWidth) {
                    mLineWidth = ta.getDimension(index, mLineWidth);
                } else if (index == R.styleable.AnimShopButton_numTextSize) {
                    mTextSize = ta.getDimension(index, mTextSize);
                } else if (index == R.styleable.AnimShopButton_hintText) {
                    mHintText = ta.getString(index);
                } else if (index == R.styleable.AnimShopButton_hintBgColor) {
                    mHintBgColor = ta.getColor(index, mHintBgColor);
                } else if (index == R.styleable.AnimShopButton_hintFgColor) {
                    mHintFgColor = ta.getColor(index, mHintFgColor);
                } else if (index == R.styleable.AnimShopButton_hingTextSize) {
                    mHingTextSize = ta.getDimensionPixelSize(index, mHingTextSize);
                } else if (index == R.styleable.AnimShopButton_hintBgRoundValue) {
                    mHintBgRoundValue = ta.getDimensionPixelSize(index, mHintBgRoundValue);
                } else if (index == R.styleable.AnimShopButton_ignoreHintArea) {
                    ignoreHintArea = ta.getBoolean(index, false);
                } else if (index == R.styleable.AnimShopButton_perAnimDuration) {
                    mPerAnimDuration = ta.getInteger(index, DEFAULT_DURATION);
                } else if (index == R.styleable.AnimShopButton_replenishText) {
                    mReplenishText = ta.getString(index);
                } else if (index == R.styleable.AnimShopButton_replenishTextColor) {
                    mReplenishTextColor = ta.getColor(index, mReplenishTextColor);
                } else if (index == R.styleable.AnimShopButton_replenishTextSize) {
                    mReplenishTextSize = ta.getDimensionPixelSize(index, mReplenishTextSize);
                }
            }
            ta.recycle();
    
    
            mAddRegion = new Region();
            mDelRegion = new Region();
            mAddPath = new Path();
            mDelPath = new Path();
    
            mAddPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            if (isAddFillMode) {
                mAddPaint.setStyle(Paint.Style.FILL);
            } else {
                mAddPaint.setStyle(Paint.Style.STROKE);
            }
            mDelPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            if (isDelFillMode) {
                mDelPaint.setStyle(Paint.Style.FILL);
            } else {
                mDelPaint.setStyle(Paint.Style.STROKE);
            }
    
            mHintPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mHintPaint.setStyle(Paint.Style.FILL);
            mHintPaint.setTextSize(mHingTextSize);
    
    
            mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mTextPaint.setTextSize(mTextSize);
            mFontMetrics = mTextPaint.getFontMetrics();
    
    
            //动画 +
            mAnimAdd = ValueAnimator.ofFloat(1, 0);
            mAnimAdd.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mAnimFraction = (float) animation.getAnimatedValue();
                    invalidate();
                }
            });
            mAnimAdd.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                }
            });
            mAnimAdd.setDuration(mPerAnimDuration);
    
            //提示语收缩动画 0-1
            mAnimReduceHint = ValueAnimator.ofFloat(0, 1);
            mAnimReduceHint.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mAnimExpandHintFraction = (float) animation.getAnimatedValue();
                    invalidate();
                }
            });
            mAnimReduceHint.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    if (mCount >= 1) {
                        //然后底色也不显示了
                        isHintMode = false;
                    }
                    if (mCount >= 1) {
                        Log.d(TAG, "现在还是》=1 开始收缩动画");
                        if (mAnimAdd != null && !mAnimAdd.isRunning()) {
                            mAnimAdd.start();
                        }
                    }
                }
    
                @Override
                public void onAnimationStart(Animator animation) {
                    if (mCount == 1) {
                        //先不显示文字了
                        isShowHintText = false;
                    }
                }
            });
            mAnimReduceHint.setDuration(ignoreHintArea ? 0 : mPerAnimDuration);
    
    
            //动画 -
            mAniDel = ValueAnimator.ofFloat(0, 1);
            mAniDel.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mAnimFraction = (float) animation.getAnimatedValue();
                    invalidate();
                }
            });
            //1-0的动画
            mAniDel.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    if (mCount == 0) {
                        Log.d(TAG, "现在还是0onAnimationEnd() called with: animation = [" + animation + "]");
                        if (mAnimExpandHint != null && !mAnimExpandHint.isRunning()) {
                            mAnimExpandHint.start();
                        }
                    }
                }
            });
            mAniDel.setDuration(mPerAnimDuration);
            //提示语展开动画
            //分析这个动画,最初是个圆。 就是left 不断减小
            mAnimExpandHint = ValueAnimator.ofFloat(1, 0);
            mAnimExpandHint.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mAnimExpandHintFraction = (float) animation.getAnimatedValue();
                    invalidate();
                }
            });
            mAnimExpandHint.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    if (mCount == 0) {
                        isShowHintText = true;
                    }
                }
    
                @Override
                public void onAnimationStart(Animator animation) {
                    if (mCount == 0) {
                        isHintMode = true;
                    }
                }
            });
            mAnimExpandHint.setDuration(ignoreHintArea ? 0 : mPerAnimDuration);
        }
    
        /**
         * 设置初始值
         *
         * @param context
         */
        private void initDefaultValue(Context context) {
            mGapBetweenCircle = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 34, context.getResources().getDisplayMetrics());
    
            isAddFillMode = true;
            mAddEnableBgColor = 0xFFFFDC5B;
            mAddEnableFgColor = Color.BLACK;
            mAddDisableBgColor = 0xff979797;
            mAddDisableFgColor = Color.BLACK;
    
            isDelFillMode = false;
            mDelEnableBgColor = 0xff979797;
            mDelEnableFgColor = 0xff979797;
            mDelDisableBgColor = 0xff979797;
            mDelDisableFgColor = 0xff979797;
    
    /*        mMaxCount = 4;
            mCount = 1;*/
    
            mRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12.5f, getResources().getDisplayMetrics());
            mCircleWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1f, getResources().getDisplayMetrics());
            mLineWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2f, getResources().getDisplayMetrics());
            mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 14.5f, getResources().getDisplayMetrics());
    
            mHintText = "加入购物车";
            mHintBgColor = mAddEnableBgColor;
            mHintFgColor = mAddEnableFgColor;
            mHingTextSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, context.getResources().getDisplayMetrics());
            mHintBgRoundValue = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, context.getResources().getDisplayMetrics());
    
            mReplenishText = "补货中";
            mReplenishTextColor = 0xfff32d3b;
            mReplenishTextSize = mHingTextSize;
    
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int wMode = MeasureSpec.getMode(widthMeasureSpec);
            int wSize = MeasureSpec.getSize(widthMeasureSpec);
            int hMode = MeasureSpec.getMode(heightMeasureSpec);
            int hSize = MeasureSpec.getSize(heightMeasureSpec);
            switch (wMode) {
                case MeasureSpec.EXACTLY:
                    break;
                case MeasureSpec.AT_MOST:
                    //不超过父控件给的范围内,自由发挥
                    int computeSize = (int) (getPaddingLeft() + mRadius * 2 +/* mGap * 2 + mTextPaint.measureText(mCount + "")*/mGapBetweenCircle + mRadius * 2 + getPaddingRight() + mCircleWidth * 2);
                    wSize = computeSize < wSize ? computeSize : wSize;
                    break;
                case MeasureSpec.UNSPECIFIED:
                    //自由发挥
                    computeSize = (int) (getPaddingLeft() + mRadius * 2 + /*mGap * 2 + mTextPaint.measureText(mCount + "")*/mGapBetweenCircle + mRadius * 2 + getPaddingRight() + mCircleWidth * 2);
                    wSize = computeSize;
                    break;
            }
            switch (hMode) {
                case MeasureSpec.EXACTLY:
                    break;
                case MeasureSpec.AT_MOST:
                    int computeSize = (int) (getPaddingTop() + mRadius * 2 + getPaddingBottom() + mCircleWidth * 2);
                    hSize = computeSize < hSize ? computeSize : hSize;
                    break;
                case MeasureSpec.UNSPECIFIED:
                    computeSize = (int) (getPaddingTop() + mRadius * 2 + getPaddingBottom() + mCircleWidth * 2);
                    hSize = computeSize;
                    break;
            }
    
    
            setMeasuredDimension(wSize, hSize);
    
            //先暂停所有动画
            cancelAllAnim();
            //复用时会走这里,所以初始化一些UI显示的参数
            initAnimSettingsByCount();
        }
    
        /**
         * 根据当前count数量 初始化 hint提示语相关变量
         */
        private void initAnimSettingsByCount() {
            if (mCount == 0) {
                // 0 不显示 数字和-号
                mAnimFraction = 1;
            } else {
                mAnimFraction = 0;
            }
    
            if (mCount == 0) {
                isHintMode = true;
                isShowHintText = true;
                mAnimExpandHintFraction = 0;
            } else {
                isHintMode = false;
                isShowHintText = false;
                mAnimExpandHintFraction = 1;
            }
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mLeft = (int) (getPaddingLeft() + mCircleWidth);
            mTop = (int) (getPaddingTop() + mCircleWidth);
            mWidth = w;
            mHeight = h;
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            if (isReplenish) {
                // 计算Baseline绘制的起点X轴坐标
                int baseX = (int) (mWidth / 2 - mReplenishPaint.measureText(mReplenishText) / 2);
                // 计算Baseline绘制的Y坐标
                int baseY = (int) ((mHeight / 2) - ((mReplenishPaint.descent() + mReplenishPaint.ascent()) / 2));
                canvas.drawText(mReplenishText, baseX, baseY, mReplenishPaint);
                return;
            }
    
    
            if (!ignoreHintArea && isHintMode) {
                //add hint 展开动画
                //if (mCount == 0) {
                //背景
                mHintPaint.setColor(mHintBgColor);
                RectF rectF = new RectF(mLeft + (mWidth - mRadius * 2) * mAnimExpandHintFraction, mTop
                        , mWidth - mCircleWidth, mHeight - mCircleWidth);
                canvas.drawRoundRect(rectF, mHintBgRoundValue, mHintBgRoundValue, mHintPaint);
                if (isShowHintText) {
                    //前景文字
                    mHintPaint.setColor(mHintFgColor);
                    // 计算Baseline绘制的起点X轴坐标
                    int baseX = (int) (mWidth / 2 - mHintPaint.measureText(mHintText) / 2);
                    // 计算Baseline绘制的Y坐标
                    int baseY = (int) ((mHeight / 2) - ((mHintPaint.descent() + mHintPaint.ascent()) / 2));
                    canvas.drawText(mHintText, baseX, baseY, mHintPaint);
                }
                //}
            } else {
    
                //动画 mAnimFraction :减 0~1, 加 1~0 ,
                //动画位移Max,
                float animOffsetMax = (mRadius * 2 + /*mGap * 2 + mTextPaint.measureText(mCount + "")*/mGapBetweenCircle);
                //透明度动画的基准
                int animAlphaMax = 255;
                int animRotateMax = 360;
    
                //左边
                //背景 圆
                if (mCount > 0) {
                    mDelPaint.setColor(mDelEnableBgColor);
                } else {
                    mDelPaint.setColor(mDelDisableBgColor);
                }
                mDelPaint.setAlpha((int) (animAlphaMax * (1 - mAnimFraction)));
    
                mDelPaint.setStrokeWidth(mCircleWidth);
                mDelPath.reset();
                //改变圆心的X坐标,实现位移
                mDelPath.addCircle(animOffsetMax * mAnimFraction + mLeft + mRadius, mTop + mRadius, mRadius, Path.Direction.CW);
                mDelRegion.setPath(mDelPath, new Region(mLeft, mTop, mWidth - getPaddingRight(), mHeight - getPaddingBottom()));
                //canvas.drawCircle(mAnimOffset + mLeft + mRadius, mTop + mRadius, mRadius, mPaint);
                canvas.drawPath(mDelPath, mDelPaint);
    
                //前景 -
                if (mCount > 0) {
                    mDelPaint.setColor(mDelEnableFgColor);
                } else {
                    mDelPaint.setColor(mDelDisableFgColor);
                }
                mDelPaint.setStrokeWidth(mLineWidth);
                //旋转动画
                canvas.save();
                canvas.translate(animOffsetMax * mAnimFraction + mLeft + mRadius, mTop + mRadius);
                canvas.rotate((int) (animRotateMax * (1 - mAnimFraction)));
            /*canvas.drawLine(mAnimOffset + mLeft + mRadius / 2, mTop + mRadius,
                    mAnimOffset + mLeft + mRadius / 2 + mRadius, mTop + mRadius,
                    mPaint);*/
                canvas.drawLine(-mRadius / 2, 0,
                        +mRadius / 2, 0,
                        mDelPaint);
                canvas.restore();
    
    
                //数量
                canvas.save();
                //平移动画
                canvas.translate(mAnimFraction * (/*mGap*/mGapBetweenCircle / 2 - mTextPaint.measureText(mCount + "") / 2 + mRadius), 0);
                //旋转动画,旋转中心点,x 是绘图中心,y 是控件中心
                canvas.rotate(360 * mAnimFraction,
                    /*mGap*/ mGapBetweenCircle / 2 + mLeft + mRadius * 2 /*+ mTextPaint.measureText(mCount + "") / 2*/,
                        mTop + mRadius);
                //透明度动画
                mTextPaint.setAlpha((int) (255 * (1 - mAnimFraction)));
                //是没有动画的普通写法,x left, y baseLine
                canvas.drawText(mCount + "", /*mGap*/ mGapBetweenCircle / 2 - mTextPaint.measureText(mCount + "") / 2 + mLeft + mRadius * 2, mTop + mRadius - (mFontMetrics.top + mFontMetrics.bottom) / 2, mTextPaint);
                canvas.restore();
    
                //右边
                //背景 圆
                if (mCount < mMaxCount) {
                    mAddPaint.setColor(mAddEnableBgColor);
                } else {
                    mAddPaint.setColor(mAddDisableBgColor);
                }
                mAddPaint.setStrokeWidth(mCircleWidth);
                float left = mLeft + mRadius * 2 + /*mGap * 2 + mTextPaint.measureText(mCount + "")*/ mGapBetweenCircle;
                mAddPath.reset();
                mAddPath.addCircle(left + mRadius, mTop + mRadius, mRadius, Path.Direction.CW);
                mAddRegion.setPath(mAddPath, new Region(mLeft, mTop, mWidth - getPaddingRight(), mHeight - getPaddingBottom()));
                //canvas.drawCircle(left + mRadius, mTop + mRadius, mRadius, mPaint);
                canvas.drawPath(mAddPath, mAddPaint);
                //前景 +
                if (mCount < mMaxCount) {
                    mAddPaint.setColor(mAddEnableFgColor);
                } else {
                    mAddPaint.setColor(mAddDisableFgColor);
                }
                mAddPaint.setStrokeWidth(mLineWidth);
                canvas.drawLine(left + mRadius / 2, mTop + mRadius, left + mRadius / 2 + mRadius, mTop + mRadius, mAddPaint);
                canvas.drawLine(left + mRadius, mTop + mRadius / 2, left + mRadius, mTop + mRadius / 2 + mRadius, mAddPaint);
            }
        }
    
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            int action = event.getAction();
            switch (action) {
                case MotionEvent.ACTION_DOWN:
                    if (isReplenish) {
                        break;
                    }
                    //hint文字模式
                    if (isHintMode) {
                        onAddClick();
                        return true;
                    } else {
                        if (mAddRegion.contains((int) event.getX(), (int) event.getY())) {
                            onAddClick();
                            return true;
                        } else if (mDelRegion.contains((int) event.getX(), (int) event.getY())) {
                            onDelClick();
                            return true;
                        }
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    break;
            }
    
    
            return super.onTouchEvent(event);
    
        }
    
        /**
         * 使用时,可以重写`onDelClick()`和` onAddClick()`方法,并在合适的时机回调`onCountAddSuccess()`和` onCountDelSuccess()`以执行动画。
         */
        protected void onDelClick() {
            if (mCount > 0) {
                mCount--;
                onCountDelSuccess();
                if (null != mOnAddDelListener) {
                    mOnAddDelListener.onDelSuccess(mCount);
                }
            } else {
                if (null != mOnAddDelListener) {
                    mOnAddDelListener.onDelFaild(mCount, IOnAddDelListener.FailType.COUNT_MIN);
                }
            }
    
        }
    
        protected void onAddClick() {
            if (mCount < mMaxCount) {
                mCount++;
                onCountAddSuccess();
                if (null != mOnAddDelListener) {
                    mOnAddDelListener.onAddSuccess(mCount);
                }
            } else {
                if (null != mOnAddDelListener) {
                    mOnAddDelListener.onAddFailed(mCount, IOnAddDelListener.FailType.COUNT_MAX);
                }
            }
        }
    
        /**
         * 数量增加成功后,使用者回调以执行动画。
         */
        public void onCountAddSuccess() {
            if (mCount == 1) {
                cancelAllAnim();
                mAnimReduceHint.start();
            } else {
                mAnimFraction = 0;
                invalidate();
            }
        }
    
        /**
         * 数量减少成功后,使用者回调以执行动画。
         */
        public void onCountDelSuccess() {
            if (mCount == 0) {
                cancelAllAnim();
                mAniDel.start();
            } else {
                mAnimFraction = 0;
                invalidate();
            }
        }
    
    
    }
    

    相关文章

      网友评论

          本文标题:购物车按钮

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