Android椭圆进度条

如上 实现这种效果 


import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;

import androidx.annotation.Nullable;


public class EllipseView  extends View {


    private int mPadding = 10;//内边距基准值
    private int mInnerCircleWidth = dp2px(140);//左右圆弧的距离  用于控制中间矩形的宽度大小


    private int mViewWidth; // 控件宽度
    private int mViewHeight; // 控件高度
    private float mViewCenterX, mViewCenterY;
    private float mCircleTopX, mCircleTopY; 
    private float mCircleBottomX, mCircleBottomY; 

    private int mRadius; // 内圆环的半径

    private int progressWidth;//进度条宽度
    private int progressIndex = 0;


    private int currentProgress=0;//当前状态值
    public EllipseView(Context context) {
        this(context, null);

    }

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

    }

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

    public EllipseView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }
    private Paint mPaint;

    private void init() {
        progressWidth = dp2px(10);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
    }


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

        setPadding(dp2px(mPadding * 2), dp2px(mPadding), dp2px(mPadding * 2), dp2px(mPadding));
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);//从约束规范中获取模式
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);//从约束规范中获取尺寸

        //在布局中设置了具体值
        if (widthMode == MeasureSpec.EXACTLY)
            mViewWidth = widthSize;

        //在布局中设置 wrap_content,控件就取能完全展示内容的宽度(同时需要考虑屏幕的宽度)
        if (widthMode == MeasureSpec.AT_MOST)
            mViewWidth = Math.min(mViewWidth, widthSize);

        //高度和宽度是2:1的关系
        mViewHeight = mViewWidth * 2;

        //保存测量宽度和测量高度
        setMeasuredDimension(mViewWidth, mViewHeight);

        mRadius = mViewWidth / 2;
        mViewCenterX = mViewWidth / 2;
        mViewCenterY = mViewHeight / 2;



        //下圆弧圆心
        mCircleTopX = mViewCenterX;
        mCircleTopY = mViewCenterY + mInnerCircleWidth / 2f + mRadius / 4;

        //上圆弧圆心
        mCircleBottomX = mViewCenterX;
        mCircleBottomY = mViewCenterY - mInnerCircleWidth / 2f - mRadius / 4;
    }

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


        mPaint.setStyle(Paint.Style.STROKE);//充满
        mPaint.setColor(getResources().getColor(R.color.color_16CEFC));
        mPaint.setStrokeWidth(progressWidth);

        //画上圆环
        canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2,
                mCircleBottomY - mRadius + progressWidth / 2,
                mCircleBottomX + mRadius - progressWidth / 2,
                mCircleBottomY + mRadius - progressWidth / 2,
                180, 180, false, mPaint);
        //画左边线
        canvas.drawLine(mCircleBottomX - mRadius + progressWidth / 2,
                mCircleBottomY,
                mCircleTopX - mRadius + progressWidth / 2,
                mCircleTopY,
                mPaint);
        //画右边线

        canvas.drawLine(mCircleBottomX + mRadius - progressWidth / 2,
                mCircleBottomY,
                mCircleBottomX + mRadius - progressWidth / 2,
                mCircleTopY,
                mPaint);


        //画下圆环
        canvas.drawArc(mCircleTopX - mRadius + progressWidth / 2,
                mCircleTopY - mRadius + progressWidth / 2,
                mCircleTopX + mRadius - progressWidth / 2,
                mCircleTopY + mRadius - progressWidth / 2,
                0,
                180,
                false,
                mPaint);


        mPaint.setColor(getResources().getColor(R.color.color_326BF7));
        mPaint.setStrokeCap(Paint.Cap.ROUND);



        //蠢办法 画各个区间的路径  从上圆中间逆时针开始  最终上圆中间结束
        if(currentProgress <= 12.5) {
            //逆时针画上左圆
            canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2,
                    mCircleBottomY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2,
                    mCircleBottomY + mRadius - progressWidth / 2,
                    269, -currentProgress * 7.2f, false, mPaint);
        } else if (currentProgress > 12.5 & currentProgress <= 37.5) {
            //左边线 从上往下
            canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2, mCircleBottomY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2, mCircleBottomY + mRadius - progressWidth / 2,
                    269, (float) (-12.5 * 7.2f), false, mPaint);
            canvas.drawLine(mCircleBottomX - mRadius + progressWidth / 2,
                    mCircleBottomY,
                    mCircleTopX - mRadius + progressWidth / 2,
                    (float) (mCircleBottomY + (currentProgress - 12.5) * ((mCircleTopY - mCircleBottomY) / 25)),
                    mPaint);
        } else if (currentProgress > 37.5 & currentProgress <= 62.5) {
            //底部半圆
            canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2, mCircleBottomY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2, mCircleBottomY + mRadius - progressWidth / 2,
                    269, (float) (-12.5 * 7.2f), false, mPaint);
            canvas.drawLine(mCircleBottomX - mRadius + progressWidth / 2,
                    mCircleBottomY,
                    mCircleTopX - mRadius + progressWidth / 2,
                    mCircleTopY,
                    mPaint);
            canvas.drawArc(mCircleTopX - mRadius + progressWidth / 2,
                    mCircleTopY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2,
                    mCircleTopY + mRadius - progressWidth / 2,
                    180, (float) -((currentProgress - 37.5) * 7.2f), false, mPaint);

        } else if (currentProgress > 62.5 & currentProgress <= 87.5) {
            //右边线 从下往上
            canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2, mCircleBottomY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2, mCircleBottomY + mRadius - progressWidth / 2,
                    269, (float) (-12.5 * 7.2f), false, mPaint);
            canvas.drawLine(mCircleBottomX - mRadius + progressWidth / 2,
                    mCircleBottomY,
                    mCircleTopX - mRadius + progressWidth / 2,
                    mCircleTopY,
                    mPaint);
            canvas.drawArc(mCircleTopX - mRadius + progressWidth / 2,
                    mCircleTopY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2,
                    mCircleTopY + mRadius - progressWidth / 2,
                    180, -(25 * 7.2f), false, mPaint);

            canvas.drawLine(mCircleTopX + mRadius - progressWidth / 2,
                    mCircleTopY,
                    mCircleBottomX + mRadius - progressWidth / 2,
                    (float) (mCircleTopY - (currentProgress - 62.5) * ((mCircleTopY - mCircleBottomY) / 25)),
                    mPaint);


        } else if (currentProgress > 87.5 & currentProgress <= 100) {
            //上半右边圆
            canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2, mCircleBottomY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2, mCircleBottomY + mRadius - progressWidth / 2,
                    269, (float) (-12.5 * 7.2f), false, mPaint);
            canvas.drawLine(mCircleBottomX - mRadius + progressWidth / 2,
                    mCircleBottomY,
                    mCircleTopX - mRadius + progressWidth / 2,
                    mCircleTopY,
                    mPaint);
            canvas.drawArc(mCircleTopX - mRadius + progressWidth / 2,
                    mCircleTopY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2,
                    mCircleTopY + mRadius - progressWidth / 2,
                    180, -(25 * 7.2f), false, mPaint);

            canvas.drawLine(mCircleTopX + mRadius - progressWidth / 2,
                    mCircleTopY,
                    mCircleBottomX + mRadius - progressWidth / 2,
                    mCircleBottomY,
                    mPaint);


            canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2,
                    mCircleBottomY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2,
                    mCircleBottomY + mRadius - progressWidth / 2,
                    0, (float) -((currentProgress - 87.5) * 7.2f), false, mPaint);

        }



        drawMyPro(canvas);

    }
    //蠢办法 慢慢算各个部分的绘画值
    private void drawMyPro(Canvas canvas) {

        if(currentProgress<progressIndex){
            if (progressIndex <= 12.5) {
                canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2,
                        mCircleBottomY - mRadius + progressWidth / 2,
                        mCircleBottomX + mRadius - progressWidth / 2,
                        mCircleBottomY + mRadius - progressWidth / 2,
                        (float) (269-currentProgress*7.2), -(progressIndex-currentProgress)* 7.2f, false, mPaint);
            } else if (progressIndex > 12.5 & progressIndex <= 37.5) {
               /* canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2, mCircleBottomY - mRadius + progressWidth / 2,
                        mCircleBottomX + mRadius - progressWidth / 2, mCircleBottomY + mRadius - progressWidth / 2,
                        269, (float) (-12.5 * 7.2f), false, mPaint);*/
                canvas.drawLine(mCircleBottomX - mRadius + progressWidth / 2,
                        (float) (mCircleBottomY+ (currentProgress - 12.5) * ((mCircleTopY - mCircleBottomY) / 25)),
                        mCircleTopX - mRadius + progressWidth / 2,
                        (float) (mCircleBottomY + (progressIndex - 12.5) * ((mCircleTopY - mCircleBottomY) / 25)),
                        mPaint);
            } else if (progressIndex > 37.5 & progressIndex <= 62.5) {
     /*           canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2, mCircleBottomY - mRadius + progressWidth / 2,
                        mCircleBottomX + mRadius - progressWidth / 2, mCircleBottomY + mRadius - progressWidth / 2,
                        269, (float) (-12.5 * 7.2f), false, mPaint);
                canvas.drawLine(mCircleBottomX - mRadius + progressWidth / 2,
                        mCircleBottomY,
                        mCircleTopX - mRadius + progressWidth / 2,
                        mCircleTopY,
                        mPaint);*/
                canvas.drawArc(mCircleTopX - mRadius + progressWidth / 2,
                        mCircleTopY - mRadius + progressWidth / 2,
                        mCircleBottomX + mRadius - progressWidth / 2,
                        mCircleTopY + mRadius - progressWidth / 2,
                        (float) (180-(currentProgress-37.5)*7.2)
                        , (float) -((progressIndex-currentProgress) * 7.2f), false, mPaint);
            } else if (progressIndex > 62.5 & progressIndex <= 87.5) {
              /*  canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2, mCircleBottomY - mRadius + progressWidth / 2,
                        mCircleBottomX + mRadius - progressWidth / 2, mCircleBottomY + mRadius - progressWidth / 2,
                        269, (float) (-12.5 * 7.2f), false, mPaint);
                canvas.drawLine(mCircleBottomX - mRadius + progressWidth / 2,
                        mCircleBottomY,
                        mCircleTopX - mRadius + progressWidth / 2,
                        mCircleTopY,
                        mPaint);
                canvas.drawArc(mCircleTopX - mRadius + progressWidth / 2,
                        mCircleTopY - mRadius + progressWidth / 2,
                        mCircleBottomX + mRadius - progressWidth / 2,
                        mCircleTopY + mRadius - progressWidth / 2,
                        180, -(25 * 7.2f), false, mPaint);*/
                canvas.drawLine(mCircleTopX + mRadius - progressWidth / 2,
                        (float) (mCircleTopY- (currentProgress - 62.5) * ((mCircleTopY - mCircleBottomY) / 25)),

                        mCircleBottomX + mRadius - progressWidth / 2,
                        (float) (mCircleTopY - (progressIndex - 62.5) * ((mCircleTopY - mCircleBottomY) / 25)),
                        mPaint);
            } else if (progressIndex > 87.5 & progressIndex <= 100) {
/*                canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2, mCircleBottomY - mRadius + progressWidth / 2,
                        mCircleBottomX + mRadius - progressWidth / 2, mCircleBottomY + mRadius - progressWidth / 2,
                        269, (float) (-12.5 * 7.2f), false, mPaint);
                canvas.drawLine(mCircleBottomX - mRadius + progressWidth / 2,
                        mCircleBottomY,
                        mCircleTopX - mRadius + progressWidth / 2,
                        mCircleTopY,
                        mPaint);
                canvas.drawArc(mCircleTopX - mRadius + progressWidth / 2,
                        mCircleTopY - mRadius + progressWidth / 2,
                        mCircleBottomX + mRadius - progressWidth / 2,
                        mCircleTopY + mRadius - progressWidth / 2,
                        180, -(25 * 7.2f), false, mPaint);

                canvas.drawLine(mCircleTopX + mRadius - progressWidth / 2,
                        mCircleTopY,
                        mCircleBottomX + mRadius - progressWidth / 2,
                        mCircleBottomY,
                        mPaint);*/
                canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2,
                        mCircleBottomY - mRadius + progressWidth / 2,
                        mCircleBottomX + mRadius - progressWidth / 2,
                        mCircleBottomY + mRadius - progressWidth / 2,
                        (float) (360-(currentProgress-87.5)*7.2), (float) -((progressIndex-currentProgress) * 7.2f), false, mPaint);
            }
        }
        /*if (progressIndex <= 12.5) {
            canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2,
                    mCircleBottomY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2,
                    mCircleBottomY + mRadius - progressWidth / 2,
                    269, -progressIndex * 7.2f, false, mPaint);
        } else if (progressIndex > 12.5 & progressIndex <= 37.5) {
            canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2, mCircleBottomY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2, mCircleBottomY + mRadius - progressWidth / 2,
                    269, (float) (-12.5 * 7.2f), false, mPaint);
            canvas.drawLine(mCircleBottomX - mRadius + progressWidth / 2,
                    mCircleBottomY,
                    mCircleTopX - mRadius + progressWidth / 2,
                    (float) (mCircleBottomY + (progressIndex - 12.5) * ((mCircleTopY - mCircleBottomY) / 25)),
                    mPaint);
        } else if (progressIndex > 37.5 & progressIndex <= 62.5) {
            canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2, mCircleBottomY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2, mCircleBottomY + mRadius - progressWidth / 2,
                    269, (float) (-12.5 * 7.2f), false, mPaint);
            canvas.drawLine(mCircleBottomX - mRadius + progressWidth / 2,
                    mCircleBottomY,
                    mCircleTopX - mRadius + progressWidth / 2,
                    mCircleTopY,
                    mPaint);
            canvas.drawArc(mCircleTopX - mRadius + progressWidth / 2,
                    mCircleTopY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2,
                    mCircleTopY + mRadius - progressWidth / 2,
                    180, (float) -((progressIndex - 37.5) * 7.2f), false, mPaint);


        } else if (progressIndex > 62.5 & progressIndex <= 87.5) {
            canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2, mCircleBottomY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2, mCircleBottomY + mRadius - progressWidth / 2,
                    269, (float) (-12.5 * 7.2f), false, mPaint);
            canvas.drawLine(mCircleBottomX - mRadius + progressWidth / 2,
                    mCircleBottomY,
                    mCircleTopX - mRadius + progressWidth / 2,
                    mCircleTopY,
                    mPaint);
            canvas.drawArc(mCircleTopX - mRadius + progressWidth / 2,
                    mCircleTopY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2,
                    mCircleTopY + mRadius - progressWidth / 2,
                    180, -(25 * 7.2f), false, mPaint);

            canvas.drawLine(mCircleTopX + mRadius - progressWidth / 2,
                    mCircleTopY,
                    mCircleBottomX + mRadius - progressWidth / 2,
                    (float) (mCircleTopY - (progressIndex - 62.5) * ((mCircleTopY - mCircleBottomY) / 25)),
                    mPaint);


        } else if (progressIndex > 87.5 & progressIndex <= 100) {
            canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2, mCircleBottomY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2, mCircleBottomY + mRadius - progressWidth / 2,
                    269, (float) (-12.5 * 7.2f), false, mPaint);
            canvas.drawLine(mCircleBottomX - mRadius + progressWidth / 2,
                    mCircleBottomY,
                    mCircleTopX - mRadius + progressWidth / 2,
                    mCircleTopY,
                    mPaint);
            canvas.drawArc(mCircleTopX - mRadius + progressWidth / 2,
                    mCircleTopY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2,
                    mCircleTopY + mRadius - progressWidth / 2,
                    180, -(25 * 7.2f), false, mPaint);

            canvas.drawLine(mCircleTopX + mRadius - progressWidth / 2,
                    mCircleTopY,
                    mCircleBottomX + mRadius - progressWidth / 2,
                    mCircleBottomY,
                    mPaint);


            canvas.drawArc(mCircleBottomX - mRadius + progressWidth / 2,
                    mCircleBottomY - mRadius + progressWidth / 2,
                    mCircleBottomX + mRadius - progressWidth / 2,
                    mCircleBottomY + mRadius - progressWidth / 2,
                    0, (float) -((progressIndex - 87.5) * 7.2f), false, mPaint);

        }
     */
        currentProgress=progressIndex;
    }


    //给控件设置进度
    public void setProgress(int progress) {
        if (progress < 0 || progress > 100) return;

        progressIndex = progress;
        postInvalidate();
    }

    private boolean isAnimFinish = true;

    public void setProgressWithAnim(final int mprogress) {
        if (mprogress < 0 || mprogress > 100 || !isAnimFinish) {
            return;
        }
        ValueAnimator va = ValueAnimator.ofInt(currentProgress, mprogress);
        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int p = (int) animation.getAnimatedValue();
                setProgress(p);

            }
        });
        va.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
                isAnimFinish = false;
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                isAnimFinish = true;
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                super.onAnimationCancel(animation);
                isAnimFinish = true;
            }
        });
        va.setDuration(1200);
        va.start();
    }

    private int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                Resources.getSystem().getDisplayMetrics());
    }


}

xml布局文件直接引入

          <EllipseView
                android:id="@+id/ellipseView"
                android:layout_width="200dp"
                android:layout_height="400dp"
      />

动态赋值

ellipseView.setProgressWithAnim(progress);//progress为进度值

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中,可以通过自定义View来绘制椭圆进度条。以下是具体步骤: 1. 创建一个自定义View类,继承自View类。 2. 在自定义View类的构造方法中初始化相关参数,如进度条的颜色、宽度等。 3. 重写onDraw方法,在该方法中实现椭圆进度条的绘制逻辑。 4. 在onDraw方法中使用canvas.drawArc方法来绘制椭圆进度条。该方法接收四个参数:圆弧的外切矩形范围、起始角度、扫过的角度、是否包含中心。可以设置起始角度为-90度,以确保进度条从顶部开始绘制。根据实际进度值计算扫过的角度,并使用paint.setStrokeWidth方法设置进度条的宽度和paint.setColor方法设置进度条的颜色。 5. 在自定义View类中添加一个用于设置进度值的方法,以便在外部调用更新进度条的显示。 下面是一个简单的自定义View示例: ``` public class OvalProgressBar extends View { private Paint paint; private RectF rectF; private int progress; public OvalProgressBar(Context context) { this(context, null); } public OvalProgressBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public OvalProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); paint = new Paint(); paint.setAntiAlias(true); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(10); paint.setColor(Color.BLUE); rectF = new RectF(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); rectF.set(0, 0, getWidth(), getHeight()); int sweepAngle = (int) (progress / 100f * 360); canvas.drawArc(rectF, -90, sweepAngle, false, paint); } public void setProgress(int progress) { this.progress = progress; invalidate(); } } ``` 可以在布局文件中使用OvalProgressBar,并调用setProgress方法来更新进度值,从而绘制对应的椭圆进度条。例如: ``` <OvalProgressBar android:layout_width="200dp" android:layout_height="200dp" app:progress="50" /> ``` 这样就可以在Android中绘制椭圆进度条了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值