Android 自定义View 实现较美观的loading进度条的绘制

这里写图片描述

1、首先绘制得底部的边框:
左右两个半圆环,中间上下两条平行线

                  //边框背景
        mPaint.setColor(mProgressBankgroundColor);
        mPaint.setStrokeWidth(mProgressBarFrameHeight);
        //移动到第一个半圆圆心
        canvas.translate(mRadius + mProgressBarFrameHeight, mProgressBarHeight / 2);
        switch (mProgressBarBankgroundStyle) {
            case SOLID:
                //进度条实心
                mPaint.setStyle(Paint.Style.FILL);
                canvas.drawCircle(0, 0, mRadius, mPaint);
                RectF rectF_Center = new RectF(0, -mRadius, mRectWidth, mRadius);
                canvas.drawRect(rectF_Center, mPaint);
                canvas.drawCircle(mRectWidth, 0, mRadius, mPaint);
                break;
            case SOLID_AND_FRAME:
                //进度条实心加边框
                mPaint.setStyle(Paint.Style.FILL);//FILL_AND_STROKE画时候  笔触右半边会和内容重合 差一半笔触!!!
                float radiusTemp = mRadius + mProgressBarFrameHeight;
                canvas.drawCircle(0, 0, radiusTemp, mPaint);
                RectF rectF = new RectF(0, -radiusTemp, mRectWidth, radiusTemp);
                canvas.drawRect(rectF, mPaint);
                canvas.drawCircle(mRectWidth, 0, radiusTemp, mPaint);
                break;
            case HOLLOW:
                //进度条空心
                mPaint.setStyle(Paint.Style.STROKE);//STROKE画时候  笔触右半边会和内容重合 差一半笔触!!!
                //
                //画 左边半圆环
                float newRadius = mRadius + mProgressBarFrameHeight / 2;
                RectF rectF_Left_Right = new RectF(-newRadius, -newRadius, newRadius, newRadius);
                canvas.drawArc(rectF_Left_Right, mStartAngle_LeftArc, 180, false, mPaint);
                canvas.save();
                canvas.translate(mRectWidth, 0);
                //画 右边半圆环
                canvas.drawArc(rectF_Left_Right, -mStartAngle_LeftArc, 180, false, mPaint);
                canvas.restore();
                //画 两条平行线
                canvas.drawLine(0, -newRadius, mRectWidth, -newRadius, mPaint);
                canvas.drawLine(0, newRadius, mRectWidth, newRadius, mPaint);
                break;
        }

2、绘制中间的填充进度
(1)画半圆左侧的任意部分,画个坐标系方便理解
这里写图片描述



        float progressBarWidthNowTemp = mProgressLoadingWidth < mRadius ? mProgressLoadingWidth : mRadius;//当前进度条不能超过左边圆的半径
        float leftArcWidth = progressBarWidthNowTemp;
        RectF rectF = new RectF(-mRadius, -mRadius, mRadius, mRadius);
        /**
         * ∠A 指的是  x轴和竖直切线的夹角  demo图见 https://code.aliyun.com/hi31588535/outside_chain/raw/master/blog_custom_view_show_pic.png
         */
        double LinBian = mRadius - leftArcWidth;//直角三角形∠A邻边
        double cosValue = LinBian / mRadius;//cosA=邻边/斜边

        double radian = Math.acos(cosValue);//反余弦   返回值单位是弧度
        // 用角度表示的角
        double angle = Math.toDegrees(radian);//转化角度

        float startAngle = (float) (mStartAngle_LeftArc + (90 - angle));
        float sweepAngle = (float) angle * 2;

        // Log.d(TAG, "onDraw: angle" + angle);//直角三角形 锐角A (∠A的) sinA=对边/斜边  cosA=邻边/斜边  tanA=对边/邻边
        canvas.drawArc(rectF, startAngle, sweepAngle, false, mPaint);

(2)画中间矩形部分

  float rectAndLeftArcMaxWidth = mProgressMaxWidth - mRadius;//所有进度条减去右边 就是左边和矩形

        float progressBarWidthNowTemp = mProgressLoadingWidth < rectAndLeftArcMaxWidth ? mProgressLoadingWidth : rectAndLeftArcMaxWidth;
        float rectWidth = progressBarWidthNowTemp - mRadius;//当前进度条减去左边半圆

        rectWidth = rectWidth < rectAndLeftArcMaxWidth ? rectWidth : rectAndLeftArcMaxWidth;
        RectF rectFCenter = new RectF(0, -mRadius, rectWidth, mRadius);
        canvas.drawRect(rectFCenter, mPaint);

(3)画半圆右侧的任意部分 分2个圆弧 1个三角形
ps:这里直接放在之前画好的坐标系上,将就看看吧
这里写图片描述

  float rectAndLeftArcMaxWidth = mProgressMaxWidth - mRadius;//所有进度条减去右边 就是左边和矩形

        float progressBarWidthNowTemp = mProgressLoadingWidth < mProgressMaxWidth ? mProgressLoadingWidth : mProgressMaxWidth;

        float rightArcWidth = progressBarWidthNowTemp - rectAndLeftArcMaxWidth;//当前进度条减去左边半圆和矩形

        float rectWidth = rectAndLeftArcMaxWidth - mRadius;

        canvas.translate(rectWidth, 0);//

        RectF rectF = new RectF(-mRadius, -mRadius, mRadius, mRadius);

        double LinBian = rightArcWidth;//直角三角形∠B邻边
        double cosValue = LinBian / mRadius;//cosB=邻边/斜边

        double radian &
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是实现水平进度条的自定义 View 的步骤: 1. 定义属性 在自定义 View 的类中定义属性,包括进度条的颜色、背景色、高度等等。 ```java public class HorizontalProgressBar extends View { private int mProgressColor; private int mBackgroundColor; private int mHeight; private int mMax; private int mProgress; ... } ``` 2. 重写 onMeasure() 方法 在 onMeasure() 方法中,设置 View 的宽度和高度,以及默认值。 ```java @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); setMeasuredDimension(width, mHeight); if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) { height = MeasureSpec.getSize(heightMeasureSpec); } else { height = mHeight; } setMeasuredDimension(width, height); } ``` 3. 重写 onDraw() 方法 在 onDraw() 方法中,绘制进度条和背景。 ```java @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); float ratio = (float) mProgress / (float) mMax; int progressWidth = (int) (getWidth() * ratio); // 绘制背景 Paint bgPaint = new Paint(); bgPaint.setColor(mBackgroundColor); canvas.drawRect(0, 0, getWidth(), getHeight(), bgPaint); // 绘制进度 Paint progressPaint = new Paint(); progressPaint.setColor(mProgressColor); canvas.drawRect(0, 0, progressWidth, getHeight(), progressPaint); } ``` 4. 设置属性 在自定义 View 的 XML 布局中设置属性,如下: ```xml <com.example.customview.HorizontalProgressBar android:id="@+id/horizontal_progress_bar" android:layout_width="match_parent" android:layout_height="wrap_content" app:progressColor="@color/colorPrimary" app:backgroundColor="@color/gray" app:height="5dp" app:max="100" app:progress="30" /> ``` 5. 在代码中使用 在代码中获取自定义 View,设置进度值。 ```java HorizontalProgressBar progressBar = findViewById(R.id.horizontal_progress_bar); progressBar.setProgress(50); ``` 以上就是实现水平进度条的自定义 View 的步骤。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值