Android自定义view实现圆形进度条

Android中实现进度条有很多种方式,自定义进度条一般是继承progressBar或继承view来实现,本篇中讲解的是第二种方式。

先上效果图:

实现圆形进度条总体来说并不难,还是跟往常一样继承view,初始化画笔,按下面的步骤一步步来就好了。对初学者来说动画效果可能比较陌生,我们可以使用属性动画中的valueAnimator来实现动画效果。

实现步骤:

1、画出一个灰色的圆环作为背景。

2、画出上层的圆环覆盖下方的圆环。

3、加入动画效果

值得注意的是怎么设置圆环和文字的位置。

画出矩形只需要传入矩形对角线的坐标即可,如果不加以处理的话画出来的圆环的边缘是不完整的,刚开始接触自定义view的同学们一定要先好好看看Android坐标系相关内容,不然很难理解位置参数为什么这样设置。

完整代码:

package com.example.floatingwindow.widget;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.DecelerateInterpolator;

import androidx.annotation.Nullable;

import com.example.floatingwindow.R;

public class ProgressBarView extends View {

    private Paint mPaintBack;
    private Paint mPaint;
    private Paint mPaintText;
    private float process;
    private int strokeWidth = 15;
    private int textSize = 20;
    private long duration = 3000;
    private float startDegree = 0;
    private float endDegree = 360;
    private String text = "完成";
    private String defaultText = "0%";


    public ProgressBarView(Context context) {
        super(context);
        init();
    }

    public ProgressBarView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

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

    private void init() {
        mPaintBack = new Paint();
        mPaintBack.setColor(getResources().getColor(R.color.gray));
        mPaintBack.setStyle(Paint.Style.STROKE);
        mPaintBack.setAntiAlias(true);
        mPaintBack.setStrokeCap(Paint.Cap.ROUND);
        mPaintBack.setStrokeWidth(strokeWidth);

        mPaint = new Paint();
        mPaint.setColor(getResources().getColor(R.color.purple_200));
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setAntiAlias(true);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(strokeWidth);

        mPaintText = new Paint();
        mPaintText.setAntiAlias(true);
        mPaintText.setStyle(Paint.Style.STROKE);
        mPaintText.setColor(Color.BLACK);
        mPaintBack.setStrokeCap(Paint.Cap.ROUND);
        mPaintText.setTextSize(sp2px(textSize));
    }

    public void setStrokeWidth(int width) {
        strokeWidth = width;
    }

    public void setTextSize(int textSize) {
        this.textSize = textSize;
    }

    public void setDuration(long duration) {
        this.duration = duration;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //创建圆环矩形
        RectF rectF = new RectF(strokeWidth, strokeWidth, getWidth() - strokeWidth, getHeight() - strokeWidth);
        //画出灰色进度条作为背景
        canvas.drawArc(rectF, 0, 360, false, mPaintBack);
        //画进度条
        canvas.drawArc(rectF, 0, process, false, mPaint);
        //计算进度
        int percent = (int) (process / 360 * 100);
        //设置文字在canvas中的位置
        Paint.FontMetrics fm = mPaintText.getFontMetrics();
        int mTxtWidth = (int) mPaintText.measureText(text, 0, defaultText.length());
        int mTxtHeight = (int) Math.ceil(fm.descent - fm.ascent);
        int x = getWidth() / 2 - mTxtWidth / 2;
        int y = getHeight() / 2 + mTxtHeight / 4;
        if (percent < 100) {
            canvas.drawText(percent + "%", x, y, mPaintText);
        } else {
            canvas.drawText(text, x, y, mPaintText);
        }
    }

    /**
     * 设置动画效果
     */
    public void start() {
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(startDegree, endDegree);
        valueAnimator.setDuration(duration);
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.addUpdateListener(animation -> {
            process = (float) animation.getAnimatedValue();
            invalidate();
        });
        valueAnimator.start();
    }

    private int sp2px(int sp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
                getResources().getDisplayMetrics());
    }
}

最后就是动画效果了,使用valueanimator,传入开始和结束的进度以及执行时间。然后每次进度发生变化时做UI刷新。

xml布局:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.example.floatingwindow.widget.ProgressBarView
        android:id="@+id/progressBar"
        android:layout_width="150dp"
        android:layout_height="150dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent">
    </com.example.floatingwindow.widget.ProgressBarView>

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        progressBar.start()

        progressBar.setOnClickListener { progressBar.start()}
    }

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,下面是一个简单的圆形进度条自定义View实现: ```java public class CircleProgressBar extends View { private float mProgress = 0; // 当前进度值 private float mMax = 100; // 最大进度值 private int mCircleWidth = 10; // 圆环宽度 private int mCircleColor = Color.GRAY; // 圆环颜色 private int mProgressColor = Color.BLUE; // 进度条颜色 private Paint mPaint; public CircleProgressBar(Context context) { super(context); init(); } public CircleProgressBar(Context context, AttributeSet attrs) { super(context, attrs); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressBar); mCircleWidth = ta.getDimensionPixelSize(R.styleable.CircleProgressBar_circleWidth, 10); mCircleColor = ta.getColor(R.styleable.CircleProgressBar_circleColor, Color.GRAY); mProgressColor = ta.getColor(R.styleable.CircleProgressBar_progressColor, Color.BLUE); ta.recycle(); init(); } private void init() { mPaint = new Paint(); mPaint.setAntiAlias(true); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int centerX = getWidth() / 2; int centerY = getHeight() / 2; int radius = getWidth() / 2 - mCircleWidth / 2; // 画圆环 mPaint.setColor(mCircleColor); mPaint.setStrokeWidth(mCircleWidth); mPaint.setStyle(Paint.Style.STROKE); canvas.drawCircle(centerX, centerY, radius, mPaint); // 画进度条 mPaint.setColor(mProgressColor); mPaint.setStrokeWidth(mCircleWidth); mPaint.setStyle(Paint.Style.STROKE); RectF rectF = new RectF(centerX - radius, centerY - radius, centerX + radius, centerY + radius); canvas.drawArc(rectF, -90, 360 * mProgress / mMax, false, mPaint); } public void setProgress(float progress) { mProgress = progress; invalidate(); } public void setMax(float max) { mMax = max; invalidate(); } } ``` 其中,我们可以设置圆环的宽度、圆环颜色、进度条颜色等属性。在onDraw()方法中,我们先画出圆环,然后再画出进度条进度条的弧度根据当前进度值和最大进度值计算得出。 使用时,可以在布局文件中添加如下代码: ```xml <com.example.customview.CircleProgressBar android:id="@+id/circle_progress_bar" android:layout_width="wrap_content" android:layout_height="wrap_content" app:circleColor="#FFA500" app:circleWidth="20dp" app:progressColor="#00BFFF" /> ``` 然后在代码中设置进度值即可: ```java CircleProgressBar circleProgressBar = findViewById(R.id.circle_progress_bar); circleProgressBar.setMax(100); circleProgressBar.setProgress(50); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吐尔洪江Coding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值