老套路先上图

先看上面的斜角进度条的实现方法:

package cn.yhsh.appwidget;import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Shader;/*** @author xiayiye5* @date 2022/9/6 17:50* 自定义progressBar进度条*/
public class BitmapUtils {public static Bitmap createProgressBitmap(Context context, long curPosition, long duration) {final int width = 240;final int height = 6;final int x_offset = Math.round(width * 0.02f);Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);Canvas canvas = new Canvas(bitmap);Paint paint = new Paint();paint.setColor(getColor(context, R.color.remote_view_progress_bar_bg_color));//draw progress bar bg.drawPath(x_offset, width, width - x_offset, 0, height, canvas, paint);if (duration == 0) {return bitmap;}if (curPosition + height > duration) {curPosition = duration;}float curWidth = (float) (width - x_offset) * curPosition / duration;if (curWidth > 0) {paint = new Paint();Shader mShader = new LinearGradient(0, 0, curWidth, height,new int[]{getColor(context, R.color.remote_view_current_position_bg_start_color),getColor(context, R.color.remote_view_current_position_bg_middle_color),getColor(context, R.color.remote_view_current_position_bg_end_color)},null, Shader.TileMode.CLAMP);paint.setShader(mShader);//draw current progress bar.drawPath(x_offset, curWidth + x_offset, curWidth, 0, height, canvas, paint);//draw progress bar thumb.final int thumbWidth = 3;paint = new Paint();paint.setColor(getColor(context, R.color.remote_view_current_position_bg_thumb_color));drawPath(curWidth + x_offset, curWidth + x_offset + thumbWidth,curWidth + thumbWidth, curWidth, height, canvas, paint);}return bitmap;}private static void drawPath(float x0, float x1, float x2, float x3, int y, Canvas canvas, Paint paint) {Path path = new Path();path.moveTo(x0, 0);path.lineTo(x1, 0);path.lineTo(x2, y);path.lineTo(x3, y);path.close();canvas.drawPath(path, paint);}private static int getColor(Context context, int colorId) {return context.getResources().getColor(colorId);}
}
再看下怎么使用:
Bitmap  progressBitmap = BitmapUtils.createProgressBitmap(this, position, 100)
imageview.setImageBitmap(progressBitmap)

再看下自定义渐变进度条的方法

package cn.yhsh.appwidget;/*** @author xiayiye5* @date 2022/9/8 13:30*/import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Paint.Cap;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;public class GoodProgressView extends View {private int[] mColors = {Color.RED, Color.MAGENTA};//进度条颜色(渐变色的2个点)private int backgroundColor = Color.GRAY;//进度条默认颜色private int textColor = Color.GRAY;//文本颜色private Paint mPaint;//画笔private int progressValue = 0;//进度值
// private RectF rect;//绘制范围public GoodProgressView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public GoodProgressView(Context context) {this(context, null);}// 获得我自定义的样式属性public GoodProgressView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);// 获得我们所定义的自定义样式属性TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.GoodProgressView, defStyle, 0);int n = a.getIndexCount();for (int i = 0; i < n; i++) {int attr = a.getIndex(i);switch (attr) {case R.styleable.GoodProgressView_startColor:// 渐变色之起始颜色,默认设置为红色mColors[0] = a.getColor(attr, Color.RED);break;case R.styleable.GoodProgressView_endColor:// 渐变色之结束颜色,默认设置为品红mColors[1] = a.getColor(attr, Color.MAGENTA);break;case R.styleable.GoodProgressView_backgroundColor:// 进度条默认颜色,默认设置为灰色backgroundColor = a.getColor(attr, Color.GRAY);break;case R.styleable.GoodProgressView_textColor:// 文字颜色,默认设置为灰色textColor = a.getColor(attr, Color.GRAY);break;}}a.recycle();mPaint = new Paint();progressValue = 0;}public void setProgressValue(int progressValue) {if (progressValue > 100) {progressValue = 100;}this.progressValue = progressValue;Log.i("customView", "log: progressValue=" + progressValue);}public void setColors(int[] colors) {mColors = colors;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int width = 0;int height = 0;/*** 设置宽度*/int specMode = MeasureSpec.getMode(widthMeasureSpec);int specSize = MeasureSpec.getSize(widthMeasureSpec);switch (specMode) {case MeasureSpec.EXACTLY:// 明确指定了width = specSize;break;case MeasureSpec.AT_MOST:// 一般为WARP_CONTENTwidth = getPaddingLeft() + getPaddingRight();break;}/*** 设置高度*/specMode = MeasureSpec.getMode(heightMeasureSpec);specSize = MeasureSpec.getSize(heightMeasureSpec);switch (specMode) {case MeasureSpec.EXACTLY:// 明确指定了height = specSize;break;case MeasureSpec.AT_MOST:// 一般为WARP_CONTENTheight = width / 10;break;}Log.i("customView", "log: w=" + width + " h=" + height);setMeasuredDimension(width, height);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);int mWidth = getMeasuredWidth();int mHeight = getMeasuredHeight();//按比例计算进度条各部分的值float unit = Math.min(((float) mWidth) / 300, ((float) mHeight) / 30);float lineWidth = 5 * unit;//线粗float innerCircleDiameter = 6 * unit;//内圆直径float outerCircleDiameter = 10 * unit;//外圆直径float wordHeight = 12 * unit;//字高//9*unit
// float wordWidth = 26*unit;//字长float offsetLength = 5 * unit;//留空
// float width = 300*unit;//绘画区域的长度float height = 30 * unit;//绘画区域的高度float progressWidth = 258 * unit;//绘画区域的长度mPaint.setAntiAlias(true);mPaint.setStrokeWidth((float) lineWidth);mPaint.setStyle(Style.STROKE);mPaint.setStrokeCap(Cap.ROUND);mPaint.setColor(Color.TRANSPARENT);float offsetHeight = height / 2;float offsetWidth = offsetLength;float section = ((float) progressValue) / 100;if (section > 1) {section = 1;}int count = mColors.length;int[] colors = new int[count];System.arraycopy(mColors, 0, colors, 0, count);//底部灰色背景,指示进度条总长度mPaint.setShader(null);mPaint.setColor(backgroundColor);canvas.drawLine(offsetWidth + section * progressWidth, offsetHeight, offsetWidth + progressWidth, offsetHeight, mPaint);//设置渐变色区域,线性渐变LinearGradient shader = new LinearGradient(0, 0, offsetWidth * 2 + progressWidth, 0, colors, new float[]{0, 0.3f,0.6f, 1f}, Shader.TileMode.CLAMP);//放射渐变RadialGradient shader1 = new RadialGradient(0, 0, offsetWidth * 2 + progressWidth, colors, new float[]{0, 0.3f, 0.6f, 1f}, Shader.TileMode.CLAMP);//扫描渐变SweepGradient shader2 = new SweepGradient(0, 0, colors, new float[]{0, 0.3f, 0.6f, 1f});
//        BitmapShader shader3 = new BitmapShader(BitmapFactory.decodeFile(""), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);//组合渐变ComposeShader shader4 = new ComposeShader(shader1, shader2, PorterDuff.Mode.DST_IN);mPaint.setShader(shader);//画出渐变色进度条canvas.drawLine(offsetWidth, offsetHeight, offsetWidth + section * progressWidth, offsetHeight, mPaint);//渐变色外圆mPaint.setStrokeWidth(1);mPaint.setStyle(Paint.Style.FILL);canvas.drawCircle(offsetWidth + section * progressWidth, offsetHeight, outerCircleDiameter / 2, mPaint);//绘制两条斜线,使外圆到进度条的连接更自然if (section * 100 > 1.8) {mPaint.setStrokeWidth(2 * unit);canvas.drawLine(offsetWidth + section * progressWidth - 6 * unit, offsetHeight - (float) 1.5 * unit,offsetWidth + section * progressWidth - 1 * unit, offsetHeight - (float) 3.8 * unit, mPaint);canvas.drawLine(offsetWidth + section * progressWidth - 6 * unit, offsetHeight + (float) 1.5 * unit,offsetWidth + section * progressWidth - 1 * unit, offsetHeight + (float) 3.8 * unit, mPaint);}//白色内圆mPaint.setShader(null);mPaint.setColor(Color.WHITE);canvas.drawCircle(offsetWidth + section * progressWidth, offsetHeight, innerCircleDiameter / 2, mPaint);//白色内圆//绘制文字--百分比mPaint.setStrokeWidth(2 * unit);mPaint.setColor(textColor);mPaint.setTextSize(wordHeight);//计算坐标使文字居中FontMetrics fontMetrics = mPaint.getFontMetrics();float fontHeight = fontMetrics.bottom - fontMetrics.top;float baseY = height / 2 + fontHeight / 2 - fontMetrics.bottom;canvas.drawText("" + progressValue + "%", progressWidth + 2 * offsetWidth, baseY, mPaint);//略微偏下,baseline}}
再看下怎么使用:

直接在xml中引用就好了

<cn.yhsh.appwidget.GoodProgressViewandroid:id="@+id/gpv_position"android:layout_width="match_parent"android:layout_height="wrap_content" />

自定义颜色可以在上面的xml中定义也可以使用下面的代码设置颜色

goodProgressView.setColors(randomColors())private fun randomColors(): IntArray {val colors = IntArray(4)val random = Random()var r: Intvar g: Intvar b: Int
//        colors[0] = Color.parseColor("#39BBE2")
//        colors[1] = Color.parseColor("#39BFB2")
//        colors[2] = Color.parseColor("#FF0000")for (i in 0 until colors.size) {r = random.nextInt(256)g = random.nextInt(256)b = random.nextInt(256)colors[i] = Color.argb(255, r, g, b)Log.i("打印颜色", "log: colors[$i]=" + Integer.toHexString(colors[i]))}return colors}

再看下自定义属性文件

<declare-styleable name="GoodProgressView"><attr name="startColor" format="color" /><attr name="endColor" format="color" /><attr name="backgroundColor" format="color" /><attr name="textColor" format="color" />
</declare-styleable>

在此感谢博主:Android自定义View实现渐变色进度条_Android_服务器之家

Android开发之绘制自定义进度条 | 渐变进度条 | 斜角进度条的方法相关推荐

  1. android listview下拉动画效果,Android开发中利用ListView实现一个渐变式的下拉刷新动画...

    Android开发中利用ListView实现一个渐变式的下拉刷新动画 发布时间:2020-11-23 16:50:31 来源:亿速云 阅读:80 作者:Leah 本篇文章给大家分享的是有关Androi ...

  2. android开发笔记之自定义开关按钮

    今天来讲讲自定义单个控件,就拿开关按钮来讲讲,相信大家见了非常多这样的了,先看看效果: 我们可以看到一个很常见的开关按钮,那就来分析分析. 首先: 这是由两张图片构成: ①一张为有开和关的背景图片 ② ...

  3. android 自定义刷新控件,Android开发中MJRefresh自定义刷新动画效果

    有时候我们对自己开发的项目经常不满意,但是我们要达到自定义刷新动画的效果有一定的难度,别着急,下面爱站技术频道和大家分享Android开发中MJRefresh自定义刷新动画效果,一起来学习吧! [一] ...

  4. android 开发 心电图绘制

    从接触android蓝牙开发到现在已两月有余,将自己一个个小小的知识点积攒起来,以便日后查阅.android蓝牙项目开发基本已完毕,抽点时间整理一下,先把今天解决的问题呈上,以后再记录蓝牙开发相关的知 ...

  5. android开发 实现动态获得app的cpu占有率并导出文件的两种方法。

    android开发 实现动态获得app的cpu占有率并导出文件的两种方法. 最近在做学校实验室的项目的时候,师兄要求我对app的性能进行评估,主要是从电量.cpu占有率.python模型的响应时间三者 ...

  6. HenCoder Android 开发进阶:自定义 View 1-5 绘制顺序

    这期是 HenCoder 自定义绘制的第 1-5 期:绘制顺序 之前的内容在这里:  HenCoder Android 开发进阶 自定义 View 1-1 绘制基础  HenCoder Android ...

  7. android view绘制中调用的函数,Android开发实践:自定义带动画的View

    前面两篇文章介绍了自定义View的onMeasure和onLayout原理,本文准备介绍自定义View的第三个关键部分,即onDraw()函数的重载. 对于一个自定义View来说,onMeasure只 ...

  8. Android开发实践:自定义ViewGroup的onLayout()分析

    Android开发中,对于自定义View,分为两种,一种是自定义控件(继承View类),另一种是自定义布局容器(继承ViewGroup).如果是自定义控件,则一般需要重载两个方法,一个是onMeasu ...

  9. 【Android 开发】SufaceView自定义相机拍照

    前段时间写了关于一篇关于调用系统相机的博客,如果需要调用系统相机和截图可以看一看这篇博客:Android学习之调用系统相机拍照.截图并保存最近发现不同手机,调用系统相机效果不太好,,所以学习Andro ...

最新文章

  1. Java项目:实现权限管理系统(java+SpringBoot+MyBatis+AOP+LayUI+Mysql)
  2. c6011取消对null指针的引用_C++中的野指针及其规避方法
  3. python画图标题为蓝色_python绘制语谱图怎么设置成黄蓝色
  4. 文献记录(part97)--MethodicallyUnifiedProcedures for a ConditionalApproachToOD,Clustering,Classification
  5. centos的mysql命令,Centos系统mysql相关命令
  6. 前端面试题——HTML基础篇
  7. C++学习之路 | PTA乙级—— 1046 划拳 (15 分)(精简)
  8. printstream_Java PrintStream clearError()方法与示例
  9. android 自动化 录制,android 自动化录制回放测试工具
  10. ImportError: cannot import name '_ellipsoid'
  11. 微服务Springcloud超详细教程+实战(二)
  12. 嵌入式linux屏幕录制,在MAC系统上进行屏幕录制
  13. 【Java】MapReduce 程序五步走的思想详细描述
  14. UVA152 Tree's a Crowd【暴力+最值】
  15. matlab线性代数对角化,工程线性代数(MATLAB版) (2007年7月)
  16. 什么是数据中心虚拟化?
  17. SSD硬盘无法格式化怎么办
  18. ES文件浏览器访问电脑共享文件夹,输入正确的密码、账号,始终在登录界面
  19. Linux和Mac下的微信电脑版electronic-wechat(非官方)
  20. 安卓APP源码和设计报告——智能垃圾桶

热门文章

  1. Qt自制简易好看的日志系统
  2. USB、USB转串口、串口通信的区别与实现
  3. oracle ogg端口,OGG报错 OGG-01223
  4. java企业人事工资管理系统
  5. Linux的声卡驱动中ALSA与OSS的区别和简单流程介
  6. 如何设计更好的游戏技能树
  7. Mac 版64位 Chrome 浏览器进入 Canary 和 Dev 分支
  8. ios开发者账号申请,以及邓白氏码的申请
  9. i9500android操作系统跑流量,三星I9500刷机包 百度云ROM54公测版 因为专注 所以精进...
  10. 【全套完结】通信原理----全套Matlab仿真实验报告