继承 View 实现 ProgressBar, 练习使用 Kotlin
参考 https://github.com/lingochamp/MagicProgressWidget
一些方法说明:
canvas clipRect
1 2
| canvas.clipRect(RectF rect) canvas.clipRect(RectF rect, Region.Op op)
|
裁剪画布,设置画布的显示区域,调用 clipRect
之后,只会显示被裁剪的区域,之外的区域不会显示。只对clipRect 之后的绘制操作有效
1 2 3 4 5 6 7
| paint.isAntiAlias = true paint.color = Color.BLACK paint.textSize = 30.0F
canvas.clipRect(100F, 100F, 350F, 600F, Region.Op.INTERSECT); canvas.drawColor(Color.RED); canvas.drawCircle(100F, 100F, 100F, paint);
|
裁剪参数:
- DIFFERENCE是第一次不同于第二次的部分显示出来
- REPLACE是显示第二次的
- REVERSE_DIFFERENCE 是第二次不同于第一次的部分显示
- INTERSECT交集显示(默认)
- UNION全部显示
- XOR补集 就是全集的减去交集剩余部分显示

canvas save
1 2
| canvas.save() canvas.restore()
|
save()
用来保存 canvas
的状态,restore()
用来恢复 canvas
到 save()
时的状态。例如对画布进行了旋转、缩放操作之后,画布坐标就变了,然后想继续使用正常的画布坐标,就可以使用: save()
-> 操作 -> restore()
-> 继续操作。
绘制 SimpleProgressBar
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| class SimpleProgressBar : View { constructor(context: Context) : super(context) constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet) constructor(context: Context, attributeSet: AttributeSet, defaultAttr: Int) : super(context, attributeSet, defaultAttr)
private var mAnimator: ValueAnimator? = null private var currentPresent = 0F private lateinit var mRectF: RectF private val backPaint = Paint() private val fillPaint = Paint() private var backColor = Color.GRAY set(value) { field = value invalidate() } private var fillColor = Color.RED set(value) { field = value invalidate() }
init { backPaint.color = backColor backPaint.isAntiAlias = true backPaint.style = Paint.Style.FILL
fillPaint.color = fillColor fillPaint.isAntiAlias = true fillPaint.style = Paint.Style.FILL setPercent(0.6F) }
fun setPercent(percent: Float, duration: Long = 2000L) { mAnimator?.cancel() mAnimator = ValueAnimator.ofFloat(currentPresent, percent) mAnimator?.duration = duration mAnimator?.addUpdateListener({ currentPresent = it.animatedValue as Float invalidate() }) mAnimator?.start() }
private var mWidth: Int = 0 private var mHeight: Int = 0 private var radius: Float = 0F
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) mRectF = RectF( paddingLeft.toFloat(), paddingTop.toFloat(), (w - paddingRight).toFloat(), (h - paddingBottom).toFloat()) mWidth = w - paddingLeft - paddingRight mHeight = h - paddingTop - paddingBottom radius = mHeight / 2F }
override fun onDraw(canvas: Canvas) { super.onDraw(canvas) canvas.save() mRectF.right = mWidth.toFloat() canvas.drawRoundRect(mRectF, radius, radius, backPaint) val fillWidth = mWidth * currentPresent when { fillWidth > 0F && fillWidth < radius * 2 -> { mRectF.right = fillWidth canvas.clipRect(mRectF) mRectF.right = radius * 2 canvas.drawRoundRect(mRectF, radius, radius, fillPaint) } fillWidth > radius -> { mRectF.right = fillWidth canvas.drawRoundRect(mRectF, radius, radius, fillPaint) } } canvas.restore() } }
|