自定义圆形播放按钮进度条

作者: 池小训 | 来源:发表于2017-10-14 15:36 被阅读187次

    前言

    由于我最近在公司开发的项目做一个音乐播放器,类似于咪咕音乐,qq音乐,网易云音乐。刚开始的需求还只是做一些简单的播放音乐功能,播放按钮也是直接拿UI给的图标,还不需要搞什么在按钮上显示进度之类的,小日子过的还算轻松,没什么大鸭梨。可是后来我们伟大的产品经理说要在歌曲列表上添加一个播放按钮,按钮上还能显示歌曲播放的进度和状态,状态分三种:默认,正在播放,结束。
    类似于


    结束_橙色.png 暂停_橙色.png

    当然,这需求并不复杂,相信学过自定义控件的朋友都有思路,而我也一开始就想到了两个解决方案:

    方案一

    做一个圆形播放进度的自定义view,然后根据进度控制播放的状态,例如在暂停时,替换成UI给的图标,结束时,用播放结束的图标。这个方案优点是省时省事,但是有个缺点,就是很难使自定义view的大小和ui给的图标随手机屏幕分辨率的改变保持一致

    方案二

    徒手画一个播放按钮,含有播放进度功能和根据播放进度画出不同的播放状态。这个方案的有点很明显,解决了方案一的缺点,但是却就是麻烦了一点,需要把图标画出来,还要控制状态。

    最终我选择了方案二,因为这方案虽然麻烦了一点,但能解决是安卓机型的适配问题啊!还有能随时自定义图标的颜色,根据UI给的图标,播放按钮不止一个颜色,如果用方案一可能多用好几个图标。

    1.在 attr.xml 中设置播放进度条的属性
       <!--自定义进度条-->
        <declare-styleable name="CustomProgress">
            <attr name="radius" format="dimension" /><!--半径-->
            <attr name="strokeWidth" format="dimension" /><!--画笔宽度-->
            <attr name="circleColor" format="color" /><!--内圆颜色-->
            <attr name="ringColor" format="color" /><!--进度条颜色-->
            <attr name="totalProgress" format="integer" /><!--总进度-->
            <attr name="textColor" format="color|reference" /><!--字体颜色-->
            <attr name="bigCircleColor" format="color" /><!--外圆颜色-->
            <attr name="rectColor" format="color" /><!--中间双竖暂停的颜色-->
        </declare-styleable>
    
    2.初始化自定义属性
        private void initAttrs(Context context, AttributeSet attrs) {
            TypedArray typeArray = context.getTheme().obtainStyledAttributes(attrs,
                    R.styleable.CustomProgress, 0, 0);
            mRadius = typeArray.getDimension(R.styleable.CustomProgress_radius, 300);
            mStrokeWidth = typeArray.getDimension(R.styleable.CustomProgress_strokeWidth, 20);
            mCircleColor = typeArray.getColor(R.styleable.CustomProgress_circleColor, Color.BLUE);
            mRingColor = typeArray.getColor(R.styleable.CustomProgress_ringColor, Color.RED);
            mTotalProgress = typeArray.getInt(R.styleable.CustomProgress_totalProgress, 100);
            mTextColor = typeArray.getColor(R.styleable.CustomProgress_textColor, Color.WHITE);
            mBigCircleColor = typeArray.getColor(R.styleable.CustomProgress_bigCircleColor, Color.WHITE);
            mRectColor = typeArray.getColor(R.styleable.CustomProgress_rectColor, Color.WHITE);
            txt = "1";
            typeArray.recycle();//注意这里要释放掉
            mRingRadius = mRadius + mStrokeWidth / 2;
        }
    
    3.实现onDraw方法
     protected void onDraw(Canvas canvas) {
    
            //计算中心点
            mXCenter = getWidth() / 2;
            mYCenter = getHeight() / 2;
            //未开始播放状态,默认显示文字,这里默认设置为1
            if (isNormal) {
                //计算文字长度
                mTxtWidth = mTextPaint.measureText(txt, 0, txt.length());
                //在中心点画文字
                canvas.drawText(txt, mXCenter - mTxtWidth / 2, mYCenter + mTxtHeight / 4, mTextPaint);
                return;
            }
            //正在播放状态或者结束状态的时候 画圆环
            canvas.drawCircle(mXCenter, mYCenter, mRadius + mStrokeWidth / 2, mBigPatient);
            canvas.drawCircle(mXCenter, mYCenter, mRadius, mCirclePaint);
            //判断是正在播放还是结束状态
            if (!isFinish) {
                //正在播放状态,画出中间双竖
                canvas.drawLine(mXCenter - mRadius / 4, mYCenter - mRadius / 2 - mStrokeWidth / 4, mXCenter - mRadius / 4, mYCenter + mRadius / 2 + mStrokeWidth / 4, mRectPaint);
                canvas.drawLine(mXCenter + mRadius / 4, mYCenter - mRadius / 2 - mStrokeWidth / 4, mXCenter + mRadius / 4, mYCenter + mRadius / 2 + mStrokeWidth / 4, mRectPaint);
            } else {
                //结束播放状态,画三角形
                canvas.drawLine(mXCenter - mRadius / 4, mYCenter - mRadius / 2 - mStrokeWidth / 5, mXCenter - mRadius / 4, mYCenter + mRadius / 2 + mStrokeWidth / 5, mBigPatient);
                canvas.drawLine(mXCenter + mRadius / 2, mYCenter, mXCenter - mRadius / 4, mYCenter - mRadius / 2, mBigPatient);
                canvas.drawLine(mXCenter + mRadius / 2 + mStrokeWidth / 5, mYCenter, mXCenter - mRadius / 4, mYCenter + mRadius / 2, mBigPatient);
                return;
            }
            //根据进度画圆弧
            if (mProgress > 0) {
                RectF oval = new RectF();
                oval.left = (mXCenter - mRingRadius);
                oval.top = (mYCenter - mRingRadius);
                oval.right = mRingRadius * 2 + (mXCenter - mRingRadius);
                oval.bottom = mRingRadius * 2 + (mYCenter - mRingRadius);
                canvas.drawArc(oval, -90, ((float) mProgress / mTotalProgress) * 360, false, mRingPaint); //
                if (mProgress == 100) {
                    isFinish = true;
                    mBigPatient.setColor(mRectColor);
                }
            }
        }
    
    4.对外暴露设置一些关键属性的方法
     //设置进度的方法
        public void setProgress(int progress) {
            mProgress = progress;
            postInvalidate();
        }
    
        //设置总进度
        public void setmTotalProgress(int totalProgress) {
            mTotalProgress = totalProgress;
        }
    
        //设置当前的按钮的播放状态
        public void setStatus(int status) {
            switch (status) {
                case NORMAL_STATUS:
                    isNormal = true;
                    mBigPatient.setColor(Color.WHITE);
                    postInvalidate();
                    break;
                case START_STATUS:
                    isFinish = false;
                    isNormal = false;
                    mBigPatient.setColor(Color.parseColor("#95ffffff"));
                    break;
                case FINISH_STATUS:
                    isFinish = true;
                    isNormal = false;
                    mBigPatient.setColor(mRectColor);
                    postInvalidate();
                    break;
            }
        }
    
        //设置默认状态的文字
        public void setText(String text) {
            this.txt = text;
        }
    
        //设置中间双竖的方法
        public void setRectColor(int color) {
            this.mRectColor = color;
            mRectPaint.setColor(mRectColor);
        }
    
    演示
    test.gif
    最后附上源码地址:

    https://github.com/zeschi/PlaySongCircleProgresssDemo/tree/master

    相关文章

      网友评论

        本文标题:自定义圆形播放按钮进度条

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