自定义ProgressBar-油表,汽车速度表控件

本文介绍了如何在Android中自定义一个漂亮的ProgressBar,形如汽车的油表或速度表。通过分析需求,使用ValueAnimator平滑过渡数值变化,详细讲解了画圆弧、刻度、指针以及指针动画的实现步骤。提供了布局文件的简单实现,并鼓励读者尝试开发更多控件。
摘要由CSDN通过智能技术生成

一、写在前面的话

今天做了个控件,觉得还挺漂亮,就拿出来给大家分享一下,主要为了给大家介绍一下ValueAnimator这个动画,确实也没啥好说的,网上一堆教程,还是说说说画这个动画好了。

二、需求分析

刚拿到需求,我们分析一下。控件有两道圆弧,第一道上面有数据段,第二段是具体数值的指示段。

数值变换的时候,需要平滑过渡,不能突兀。

三、开始画。

1、画圆弧

  private void drawArc(Canvas canvas) {
        mBgPaint.setStrokeWidth(mProgressSize);
        canvas.drawArc(mProgressSize * lineSize, mProgressSize * lineSize, mWidth - mProgressSize * lineSize, mHeight - mProgressSize * lineSize, 150, 240, false, mBgPaint);
        //画推荐度数
        canvas.drawArc(mProgressSize * lineSize, mProgressSize * lineSize, mWidth - mProgressSize * lineSize, mHeight - mProgressSize * lineSize, 150 + lowProgress * 240 / 100, (highProgress - lowProgress) * 240 / 100, false, mProgressPaint);
        //画推荐度数的值
        int r = mWidth / 2 - mProgressSize;
        int x = getArcX(150 + lowProgress * 240 / 100, r);
        int y = getArcY(150 + lowProgress * 240 / 100, r);
        int x2 = getArcX(150 + highProgress * 240 / 100, r);
        int y2 = getArcY(150 + highProgress * 240 / 100, r);
        if (x < mWidth / 2) {
            x = x - 13;
        } else {
            y = y + 7;
            x = x - 3;

        }
        if (x2 < mWidth / 2) {
            x2 = x2 - 13;
        } else {
            x2 = x2 - 3;

            y2 = y2 + 7;

        }
        canvas.drawText(stringLowProgress, x, y, mTextPaint);
        canvas.drawText(stringHighProgress, x2, y2, mTextPaint);

        mBgPaint.setStrokeWidth(mProgressSize / 3);
        canvas.drawArc(mProgressSize * offset, mProgressSize * offset, mWidth - mProgressSize * offset, mHeight - mProgressSize * offset, 150, 240, false, mBgPaint);
    }

为什么会/100呢,因为这里我把进度放大了一百倍,为了值的变化更流畅。

2、画刻度

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void drawLine(Canvas canvas) {
        canvas.drawArc(mProgressSize * lineSize, mProgressSize * lineSize, mWidth - mProgressSize * lineSize, mHeight - mProgressSize * lineSize, 150 + 6 - 1, 2, false, mWhitePaint);
        for (int i = 1; i < 10; i++) {
            canvas.drawArc(mProgressSize * lineSize, mProgressSize * lineSize, mWidth - mProgressSize * lineSize, mHeight - mProgressSize * lineSize, 150 + 24 * i - 1, 2, false, mWhitePaint);
        }
        canvas.drawArc(mProgressSize * lineSize, mProgressSize * lineSize, mWidth - mProgressSize * lineSize, mHeight - mProgressSize * lineSize, 30 - 6 - 1, 2, false, mWhitePaint);
    }

这里的刻度我们画一小段白色的圆弧,大家可以根据自己的要求改一下。

3、画指针


    private void drawProgress(Canvas canvas) {
        //计算当前的角度
        int angle = 150 + mProgress * 240 / mMaxProgress;
        int r = mWidth / 2 - mProgressSize * offset;
        int cx = getArcX(angle, r);
        int cy = getArcY(angle, r);
        canvas.drawCircle(cx, cy, 4, mProgressPaint);

        //圆外一点的坐标
        int x = getArcX(angle, r + 35);
        int y = getArcY(angle, r + 35);

        //控制点1
        int co1x = getArcX(angle - 4, r + 5);
        int co1y = getArcY(angle - 4, r + 5);
        //控制点2
        int co2x = getArcX(angle + 4, r + 5);
        int co2y = getArcY(angle + 4, r + 5);
        path.reset();
        path.moveTo(co1x, co1y);
        path.lineTo(co2x, co2y);
        path.lineTo(x, y);
        path.lineTo(co1x, co1y);
        canvas.drawPath(path, mSmallWhitePaint);
        canvas.drawCircle(cx, cy, 1, mWhitePaint);


    }

4、指针动画

    //    /**
//     * 进度显示动画效果初始化
//     */
    private void initValueAnimator() {
        valueAnimator = new ValueAnimator();
        valueAnimator.setInterpolator(interpolator);
        valueAnimator.addUpdateListener(new ValueAnimatorListenerImp());
    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现圆弧进度条的自定义ProgressBar,可以使用Canvas和Paint来绘制。 首先,创建一个自定义ProgressBar类,继承自ProgressBar类,并实现构造方法和onDraw方法: ``` public class CircleProgressBar extends ProgressBar { private Paint paint; // 画笔 private int roundColor; // 圆环颜色 private int progressColor; // 进度条颜色 private int textColor; // 文字颜色 private float textSize; // 文字大小 private float roundWidth; // 圆环宽度 private int max; // 最大进度 private boolean textIsDisplayable; // 是否显示进度文字 private int style; // 进度条样式 public static final int STROKE = 0; public static final int FILL = 1; public CircleProgressBar(Context context) { this(context, null); } public CircleProgressBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleProgressBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // 获取自定义属性的值 TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressBar); roundColor = mTypedArray.getColor(R.styleable.CircleProgressBar_roundColor, Color.RED); progressColor = mTypedArray.getColor(R.styleable.CircleProgressBar_progressColor, Color.GREEN); textColor = mTypedArray.getColor(R.styleable.CircleProgressBar_textColor, Color.GREEN); textSize = mTypedArray.getDimension(R.styleable.CircleProgressBar_textSize, 15); roundWidth = mTypedArray.getDimension(R.styleable.CircleProgressBar_roundWidth, 5); max = mTypedArray.getInteger(R.styleable.CircleProgressBar_max, 100); textIsDisplayable = mTypedArray.getBoolean(R.styleable.CircleProgressBar_textIsDisplayable, true); style = mTypedArray.getInt(R.styleable.CircleProgressBar_style, 0); mTypedArray.recycle(); // 初始化画笔 paint = new Paint(); } @Override protected synchronized void onDraw(Canvas canvas) { super.onDraw(canvas); // 获取圆心坐标和半径 int centerX = getWidth() / 2; int centerY = getHeight() / 2; int radius = (int) (centerX - roundWidth / 2); // 绘制圆环 paint.setColor(roundColor); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(roundWidth); paint.setAntiAlias(true); canvas.drawCircle(centerX, centerY, radius, paint); // 绘制进度条 paint.setStrokeWidth(roundWidth); paint.setColor(progressColor); RectF oval = new RectF(centerX - radius, centerY - radius, centerX + radius, centerY + radius); switch (style) { case STROKE: paint.setStyle(Paint.Style.STROKE); canvas.drawArc(oval, 0, 360 * getProgress() / getMax(), false, paint); break; case FILL: paint.setStyle(Paint.Style.FILL_AND_STROKE); if (getProgress() != 0) canvas.drawArc(oval, 0, 360 * getProgress() / getMax(), true, paint); break; } // 绘制文字 paint.setStrokeWidth(0); paint.setColor(textColor); paint.setTextSize(textSize); paint.setTypeface(Typeface.DEFAULT_BOLD); int percent = (int) (((float) getProgress() / (float) getMax()) * 100); if (textIsDisplayable && percent >= 0) { String text = percent + "%"; float textWidth = paint.measureText(text); canvas.drawText(text, centerX - textWidth / 2, centerY + textSize / 2, paint); } } } ``` 在这个类中,我们定义了几个自定义属性,包括圆环颜色、进度条颜色、文字颜色、文字大小、圆环宽度、最大进度、是否显示进度文字、进度条样式等。在构造方法中,我们获取了这些属性的值,并初始化了画笔。在onDraw方法中,我们首先获取了圆心坐标和半径,然后使用画笔绘制了圆环和进度条,最后绘制了进度文字。 接下来,在布局文件中使用这个自定义ProgressBar: ``` <com.example.circleprogressbar.CircleProgressBar android:id="@+id/circle_progressbar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" app:roundColor="#cccccc" app:roundWidth="5dp" app:progressColor="#FF4081" app:textColor="#FF4081" app:textSize="20sp" app:textIsDisplayable="true" app:style="STROKE" /> ``` 最后,在Java代码中设置进度值即可: ``` CircleProgressBar circleProgressBar = findViewById(R.id.circle_progressbar); circleProgressBar.setProgress(50); // 设置进度为50% ``` 这样就完成了自定义的圆弧进度条的实现。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值