kotlin版的自定义圆形进度条git
大多数启动页都会带个进度条加载样式,因此就本身用kotlin从新写了一个,若是真的要很炫酷仍是有不少东西能够附加的github
一个简单的进度条基本组成就是一个背景环,一个进度环,须要注意的就是绘制的方式了canvas
由于圆形进度条是宽高对等的,咱们定义view宽高可能不是对等的,因此绘制的时候须要计算中间绘制,否则绘制的结果可能不是你理想的,好比下面右上角ide
固然,若是只是两个环,感受有点丑,不是很美观,能够添加一点元素让它稍微的美观一点,好比绘制一个进度百分比提示文字,圆环自定义颜色,中心在绘制一个中心圆,这样经过配置颜色要比两个单调的圆环美观许多字体
而后还能够加入一点初始化或者结束的view动画,这边我加了一个进入缩放动画,开始拿起键盘一把梭动画
1.初始化spa
画笔,配置颜色背景,字体,进度等都须要用到自定义属性,因此初始化的时候须要把这些参数都实例化,而后刚才加入的缩放动画也是在初始化里3d
在xml里定义好stylecode
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="circleProgress"> <attr name="circle_max" format="float" /> <attr name="circle_progress" format="float" /> <attr name="circle_width" format="dimension" /> <attr name="circle_progress_color" format="color" /> <attr name="circle_color" format="color" /> <attr name="circle_text_color" format="color" /> <attr name="circle_text_size" format="dimension" /> <attr name="circle_text_isBold" format="boolean" /> <attr name="circle_center_color" format="color" /> </declare-styleable> </resources>
而后编写init方法orm
private fun init() { //自定义属性 val attributes: TypedArray = context.obtainStyledAttributes( attrs, R.styleable.circleProgress ) mStrokeWidth = attributes.getDimension(R.styleable.circleProgress_circle_width, 1f) max = attributes.getFloat(R.styleable.circleProgress_circle_max, 100f) mProgress = attributes.getFloat(R.styleable.circleProgress_circle_progress, 0f) val bgColor = attributes.getColor(R.styleable.circleProgress_circle_color,Color.GRAY) val progressColor = attributes.getColor(R.styleable.circleProgress_circle_progress_color,Color.BLUE) val textColor = attributes.getColor(R.styleable.circleProgress_circle_text_color,Color.BLACK) val textSize = attributes.getDimension(R.styleable.circleProgress_circle_text_size,SizeUtils.dp2px(10f).toFloat()) val isBold = attributes.getBoolean(R.styleable.circleProgress_circle_text_isBold,false) val centerColor = attributes.getColor(R.styleable.circleProgress_circle_center_color,Color.TRANSPARENT) attributes.recycle() //圆环画笔 bgPaint = Paint() bgPaint.style = Paint.Style.STROKE bgPaint.strokeWidth = mStrokeWidth bgPaint.color = bgColor bgPaint.isAntiAlias = true //中心圆画笔 centerPaint = Paint() centerPaint.style = Paint.Style.FILL centerPaint.color = centerColor centerPaint.isAntiAlias = true //进度条画笔 tintPaint = Paint() tintPaint.style = Paint.Style.STROKE tintPaint.strokeWidth = mStrokeWidth tintPaint.strokeCap = Paint.Cap.ROUND tintPaint.color = progressColor tintPaint.isAntiAlias = true //文字画笔 textPaint = Paint() textPaint.style = Paint.Style.FILL textPaint.textSize = textSize textPaint.textAlign = Paint.Align.CENTER textPaint.isFakeBoldText = isBold textPaint.color = textColor textPaint.isAntiAlias = true initAnimation() }
2.测量
由于宽高是不可控的,你不知道具体设置成什么样子,有的是宽高尺寸同样,有的是宽大于高等,因此圆形直径须要取最小值,这样才能绘制成一个完整的圆形
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) mWidth = getRealSize(widthMeasureSpec) mHeight = getRealSize(heightMeasureSpec) /** 直径 - 等宽高充满 | 当宽高不一致时,取最小的画圆 */ val diameter = min(mWidth,mHeight) //半径 mRadius = diameter / 2f - mStrokeWidth /** 进度条绘制区域 */ val mX = mWidth/2f-diameter/2 val mY = mHeight/2f-diameter/2 mRect = RectF(mX + mStrokeWidth, mY + mStrokeWidth, mX + diameter - mStrokeWidth, mY + diameter - mStrokeWidth) setMeasuredDimension(mWidth,mHeight) }
3.draw
圆形直接drawCircle绘制,进度条就须要绘制扇形了,而后经过传过来的进度条,计算扇形的角度,百分比文字就是在圆形中心点绘制
override fun onDraw(canvas: Canvas?) { super.onDraw(canvas) val progress = mProgress / max * 360 //绘制圆形 canvas!!.drawCircle(mWidth / 2f, mHeight / 2f, mRadius, bgPaint) //绘制中心圆 canvas.drawCircle(mWidth / 2f, mHeight / 2f, mRadius, centerPaint) //绘制进度 canvas.drawArc(mRect, -90f, progress, false, tintPaint) //绘制文字(百分比) val percentage: Int = (mProgress / max * 100).toInt() val centerY = mHeight / 2 + mStrokeWidth / 2 canvas.drawText("${percentage}%", mWidth / 2f, centerY, textPaint) }
就是这么简单,主要逻辑其实就在测量跟绘制
而后对外扩展设置进度,刷新视图
使用:
binding.pbTime.setProgress(count)
这里模拟一下加载进度,效果图见最上方