Android 自定义View 之 圆环进度条

这篇具有很好参考价值的文章主要介绍了Android 自定义View 之 圆环进度条。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

  很多时候我们会使用进度条,而Android默认的进度条是长条的,从左至右。而在日常开发中,有时候UI为了让页面更美观,就需要用到圆环进度条,那么本文就是通过自定义写一个圆环进度条,首先看一下效果图:

Android 自定义View 之 圆环进度条

正文

  关于自定义View的基础知识就不再做过多的讲解了,我们直接进入正题,这一次我们不需要再去创建项目了,就用我之前创建的EasyView。

一、XML样式

  根据上面的效果图,我们首先来确定XML中的属性样式,修改attrs.xml的代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--文字颜色-->
    <attr name="textColor" format="color|reference" />
    <!--文字大小-->
    <attr name="textSize" format="dimension" />
    <!--蓝牙地址输入控件-->
    <declare-styleable name="MacAddressEditText">
        <!-- 方框大小,宽高一致 -->
        <attr name="boxWidth" format="dimension" />
        <!-- 方框背景颜色 -->
        <attr name="boxBackgroundColor" format="color|reference" />
        <!-- 方框描边颜色 -->
        <attr name="boxStrokeColor" format="color|reference" />
        <!-- 方框描边宽度 -->
        <attr name="boxStrokeWidth" format="dimension" />
        <!--文字颜色-->
        <attr name="textColor" />
        <!--文字大小-->
        <attr name="textSize" />
        <!--分隔符,: 、- -->
        <attr name="separator" format="string|reference" />
    </declare-styleable>
    <!--圆形进度条控件-->
    <declare-styleable name="CircularProgressBar">
        <!--半径-->
        <attr name="radius" format="dimension" />
        <!--进度条宽度-->
        <attr name="strokeWidth" format="dimension" />
        <!--进度条背景颜色-->
        <attr name="progressbarBackgroundColor" format="color|reference" />
        <!--进度条进度颜色-->
        <attr name="progressbarColor" format="color|reference" />
        <!--最大进度-->
        <attr name="maxProgress" format="integer" />
        <!--当前进度-->
        <attr name="progress" format="integer" />
        <!--文字-->
        <attr name="text" format="string" />
        <!--文字颜色-->
        <attr name="textColor" />
        <!--文字大小-->
        <attr name="textSize" />
    </declare-styleable>
</resources>

  这里你会发现一个改变,那就是文字颜色和文字大小的属性从之前的declare-styleable中抽出来了,因为我们可能多个自定义控件会用到同样的属性,那么根据属性不可重名的原则,我们需要抽离出来,然后在declare-styleable引用。

Android 自定义View 之 圆环进度条

二、构造方法

  现在属性样式已经有了,下一步就是写自定义View的构造方法了,在com.llw.easyview包下新建一个CircularProgressBar类,里面的代码如下所示:

public class CircularProgressBar extends View {

    /**
     * 半径
     */
    private int mRadius;
    /**
     * 进度条宽度
     */
    private int mStrokeWidth;

    /**
     * 进度条背景颜色
     */
    private int mProgressbarBgColor;

    /**
     * 进度条进度颜色
     */
    private int mProgressColor;

    /**
     * 开始角度
     */
    private int mStartAngle = 0;

    /**
     * 当前角度
     */
    private float mCurrentAngle = 0;

    /**
     * 结束角度
     */
    private int mEndAngle = 360;
    /**
     * 最大进度
     */
    private float mMaxProgress;
    /**
     * 当前进度
     */
    private float mCurrentProgress;
    /**
     * 文字
     */
    private String mText;
    /**
     * 文字颜色
     */
    private int mTextColor;
    /**
     * 文字大小
     */
    private float mTextSize;
    /**
     * 动画的执行时长
     */
    private long mDuration = 1000;
    /**
     * 是否执行动画
     */
    private boolean isAnimation = false;
    
    public CircularProgressBar(Context context) {
        this(context, null);
    }

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

    public CircularProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CircularProgressBar);
        mRadius = array.getDimensionPixelSize(R.styleable.CircularProgressBar_radius, 80);
        mStrokeWidth = array.getDimensionPixelSize(R.styleable.CircularProgressBar_strokeWidth, 8);
        mProgressbarBgColor = array.getColor(R.styleable.CircularProgressBar_progressbarBackgroundColor, ContextCompat.getColor(context, R.color.teal_700));
        mProgressColor = array.getColor(R.styleable.CircularProgressBar_progressbarColor, ContextCompat.getColor(context, R.color.teal_200));
        mMaxProgress = array.getInt(R.styleable.CircularProgressBar_maxProgress, 100);
        mCurrentProgress = array.getInt(R.styleable.CircularProgressBar_progress, 0);
        String text = array.getString(R.styleable.CircularProgressBar_text);
        mText = text == null ? "" : text;
        mTextColor = array.getColor(R.styleable.CircularProgressBar_textColor, ContextCompat.getColor(context, R.color.black));
        mTextSize = array.getDimensionPixelSize(R.styleable.CircularProgressBar_textSize, (int) TypedValue
                .applyDimension(TypedValue.COMPLEX_UNIT_SP, 14, getResources().getDisplayMetrics()));
        array.recycle();
    }
}

  这里声明了一些变量,然后写了3个构造方法,在第三个构造方法中进行属性的赋值。

三、测量

  这里测量就比较简单了,当然这是相对于之前的那个Mac地址输入框来说的,代码如下所示:

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = 0;
        switch (MeasureSpec.getMode(widthMeasureSpec)) {
            case MeasureSpec.UNSPECIFIED:
            case MeasureSpec.AT_MOST:   //wrap_content
                width = mRadius * 2;
                break;
            case MeasureSpec.EXACTLY:   //match_parent
                width = MeasureSpec.getSize(widthMeasureSpec);
                break;
        }
        //Set the measured width and height
        setMeasuredDimension(width, width);
    }

  因为不需要进行子控件处理,所以我们只要一个圆环就可以了,文字在圆环中间绘制,下面再看绘制的方法。

四、绘制

  绘制这里稍微代码量多一些,因为需要绘制的内容有进度条背景、进度条、中间文字三个,绘制的代码如下所示:

    @Override
    protected void onDraw(Canvas canvas) {
        int centerX = getWidth() / 2;
        RectF rectF = new RectF();
        rectF.left = mStrokeWidth;
        rectF.top = mStrokeWidth;
        rectF.right = centerX * 2 - mStrokeWidth;
        rectF.bottom = centerX * 2 - mStrokeWidth;

        //绘制进度条背景
        drawProgressbarBg(canvas, rectF);
        //绘制进度
        drawProgress(canvas, rectF);
        //绘制中心文本
        drawCenterText(canvas, centerX);
    }

  在绘制之前首先要确定中心点,因为我们是一个圆环,实际上也是一个圆,圆的宽高一样,所以中心点的x、y轴的位置就是一样的,然后是确定一个矩形的左上和右下两个位置的坐标点,通过这两个点就能绘制一个矩形,接下来就是绘制进度条背景。

① 绘制进度条背景

    /**
     * 绘制进度条背景
     */
    private void drawProgressbarBg(Canvas canvas, RectF rectF) {
        Paint mPaint = new Paint();
        //画笔的填充样式,Paint.Style.STROKE 描边
        mPaint.setStyle(Paint.Style.STROKE);
        //圆弧的宽度
        mPaint.setStrokeWidth(mStrokeWidth);
        //抗锯齿
        mPaint.setAntiAlias(true);
        //画笔的颜色
        mPaint.setColor(mProgressbarBgColor);
        //画笔的样式 Paint.Cap.Round 圆形
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        //开始画圆弧
        canvas.drawArc(rectF, mStartAngle, mEndAngle, false, mPaint);
    }

  因为背景是一个圆环,所以这里的画笔设置就比较注意一些,看一下就会了,这里最重要的是drawArc,用于绘制圆弧,像下图这样,画了4/1的背景。

Android 自定义View 之 圆环进度条
下面绘制进度

② 绘制进度

    /**
     * 绘制进度
     */
    private void drawProgress(Canvas canvas, RectF rectF) {
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(mStrokeWidth);
        paint.setColor(mProgressColor);
        paint.setAntiAlias(true);
        paint.setStrokeCap(Paint.Cap.ROUND);
        if (!isAnimation) {
            mCurrentAngle = 360 * (mCurrentProgress / mMaxProgress);
        }
        canvas.drawArc(rectF, mStartAngle, mCurrentAngle, false, paint);
    }

  这里的进度值就要根据当前的参数进行处理了,这里有一个变量进行判断处理,主要作用就是是否进行动画绘制。

③ 绘制文字

    /**
     * 绘制中心文字
     */
    private void drawCenterText(Canvas canvas, int centerX) {
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(mTextColor);
        paint.setTextAlign(Paint.Align.CENTER);
        paint.setTextSize(mTextSize);
        Rect textBounds = new Rect();
        paint.getTextBounds(mText, 0, mText.length(), textBounds);
        canvas.drawText(mText, centerX, textBounds.height() / 2 + getHeight() / 2, paint);
    }

绘制文字的规则还是和之前一样。

五、API方法

  还需要提供一些方法在代码中调用,下面是这些方法的代码:

    /**
     * 设置当前进度
     */
    public void setProgress(float progress) {
        if (progress < 0) {
            throw new IllegalArgumentException("Progress value can not be less than 0");
        }
        if (progress > mMaxProgress) {
            progress = mMaxProgress;
        }
        mCurrentProgress = progress;
        mCurrentAngle = 360 * (mCurrentProgress / mMaxProgress);
        setAnimator(0, mCurrentAngle);
    }

    /**
     * 设置文本
     */
    public void setText(String text) {
        mText = text;
    }

    /**
     * 设置文本的颜色
     */
    public void setTextColor(int color) {
        if (color <= 0) {
            throw new IllegalArgumentException("Color value can not be less than 0");
        }
        mTextColor = color;
    }

    /**
     * 设置文本的大小
     */
    public void setTextSize(float textSize) {
        if (textSize <= 0) {
            throw new IllegalArgumentException("textSize can not be less than 0");
        }
        mTextSize = textSize;
    }


    /**
     * 设置动画
     *
     * @param start  开始位置
     * @param target 结束位置
     */
    private void setAnimator(float start, float target) {
        isAnimation = true;
        ValueAnimator animator = ValueAnimator.ofFloat(start, target);
        animator.setDuration(mDuration);
        animator.setTarget(mCurrentAngle);
        //动画更新监听
        animator.addUpdateListener(valueAnimator -> {
            mCurrentAngle = (float) valueAnimator.getAnimatedValue();
            invalidate();
        });
        animator.start();
    }

  那么到此为止这个自定义View就完成了,下面我们可以在MainActivity中使用了。

六、使用

  先修改activity_main.xml的代码,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="16dp"
    tools:context=".MainActivity">

    <com.easy.view.MacAddressEditText
        android:id="@+id/mac_et"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:boxBackgroundColor="@color/white"
        app:boxStrokeColor="@color/black"
        app:boxStrokeWidth="2dp"
        app:boxWidth="48dp"
        app:separator=":"
        app:textColor="@color/black"
        app:textSize="16sp" />

    <Button
        android:id="@+id/btn_mac"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:text="获取地址" />

    <com.easy.view.CircularProgressBar
        android:id="@+id/cpb_test"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        app:maxProgress="100"
        app:progress="10"
        app:progressbarBackgroundColor="@color/purple_500"
        app:progressbarColor="@color/purple_200"
        app:radius="80dp"
        app:strokeWidth="16dp"
        app:text="10%"
        app:textColor="@color/teal_200"
        app:textSize="28sp" />

    <Button
        android:id="@+id/btn_set_progress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:text="随机设置进度" />
</LinearLayout>

首先要注意看是否能够预览,我这里是可以预览的,如下图所示:

Android 自定义View 之 圆环进度条

在MainActivity中使用,修改onCreate()方法中的代码,如下所示:

        //圆形进度条操作
        CircularProgressBar cpbTest = findViewById(R.id.cpb_test);
        Button btnSetProgress = findViewById(R.id.btn_set_progress);
        btnSetProgress.setOnClickListener(v -> {
            int progress = Math.abs(new Random().nextInt() % 100);
            Toast.makeText(this, "" + progress, Toast.LENGTH_SHORT).show();
            cpbTest.setText(progress + "%");
            cpbTest.setProgress(progress);
        });

运行效果如下图所示:

Android 自定义View 之 圆环进度条

七、源码

  顺便说一下,我打算把这个项目做成一个开源仓库,提交到mavenCentral()中,后面使用的话就可以通过这个引入依赖的方式进行调用,会很方便,后面会单独出一篇文章讲述这个仓库。

如果对你有所帮助的话,不妨 Star 或 Fork,山高水长,后会有期~

源码地址:EasyView文章来源地址https://www.toymoban.com/news/detail-496384.html

到了这里,关于Android 自定义View 之 圆环进度条的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [Uni-app] 微信小程序的圆环进度条

    效果图: 组件完整代码如下: 调用页面:

    2024年04月29日
    浏览(28)
  • android 自定义八边形进度条

    自定义八边形动画效果图如下 绘制步骤: 1.先绘制橙色底部八边形实心 2.黑色画笔绘制第二层,让最外层显示一条线条宽度即可 3.再用黄色画笔绘制黄色部分 4.使用渐变画笔根据当前进度绘制覆盖黄色部分 5.使用黑色画笔根据当前进度绘制刻度条 6.黑色画笔绘制第三层留出黄

    2024年01月18日
    浏览(22)
  • Android ProgressBar设置成横向进度条并自定义进度条颜色

    如何将ProgressBar设置成横向进度条并修改进度条颜色? 设置为横向进度条: style=\\\"@style/Widget.AppCompat.ProgressBar.Horizontal\\\" 设置进度条颜色: 自定一个文件名为progress_style_h_scene的drawable 将自定义的drawable设置到ProgressBar的android:progressDrawable属性中

    2024年02月13日
    浏览(24)
  • Android自定义View流程

    在开发中,View视图具有非常重要的作用,它是直接呈现给使用者的,因此向用户展示精美高效的View视图很有意义。Android系统提供了丰富的视图组件,如TextView、ImageView、Button等,还提供了RelativeLayout、LinearLayout、FrameLayout等组合组件,使用这些组件搭配能实现良好的视图效果

    2024年04月11日
    浏览(33)
  • android 自定义圆角View

    public class CustomView extends View {     private float cornerRadius;     public CustomView(Context context) {         super(context);         init();     }     public CustomView(Context context, AttributeSet attrs) {         super(context, attrs);         TypedArray typedArray = context.obt

    2024年02月11日
    浏览(34)
  • android开发之Android 自定义滑动解锁View

    自定义滑动解锁View 需求如下: 近期需要做一个类似屏幕滑动解锁的功能,右划开始,左划暂停。 需求效果图如下 实现效果展示 自定义view如下 /** Desc 自定义滑动解锁View Author ZY Mail sunnyfor98@gmail.com Date 2021/5/17 11:52 */ @SuppressLint(“ClickableViewAccessibility”) class SlideSwitchButton :

    2024年02月13日
    浏览(24)
  • Android:绘制自定义View人脸识别框

    项目开发需要自定义View实现一个人脸框,代码实现很平常,一些细节记录一下,方便以后查阅。 代码实现: FaceView.java 注意: 这里我把FaceView的layout_width、layout_height都设置成了\\\"match_parent\\\" 这里面有个 坑 容易踩到 本次开发时,xml中FaceView控件往上一直到第一层父布局宽、高

    2024年02月09日
    浏览(50)
  • Android 自定义View 之 Dialog弹窗

      在日常开发中用到弹窗是比较多的,常用于提示作用,比如错误操作提示,余额不足提示,退出登录提示等,还有用于数据展示的弹窗,上拉弹窗等等,主要为了简化在日常开发中的使用。   Android中的Dialog弹窗是一种用于展示特定信息或者在用户需要进行某些操作时

    2024年02月16日
    浏览(28)
  • [Android]自定义RecyclerView中View的动画

    官方有一个默认Item动画类DafaultItemAnimator,其中 DefaultItemAnimator 继承了SimpleItemAnimator 继承了 RecyclerView.ItemAnimator SimpleItemAnimator 它是一个包装类,用来判断当前的ViewHolder到底是执行移动、移除、添加或者改变等行为。 DefaultItemAnimator 是执行具体动画类,它负责将viewHolder初始化

    2024年02月11日
    浏览(50)
  • Android 自定义View实战—制作一个简易输入框

    这次我们来做一个简易输入框,可以用于密码输入和验证码输入。 依然在EasyView中进行创建,在 com.easy.view 下新建一个 EasyEditText ,继承自 View ,实现里面的构造方法。 ① 构造方法 然后我们继承自 View ,重写里面的构造方法,代码如下: 下面就可以增加样式了。 ② XML样式

    2024年02月10日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包