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)
這裏模擬一下加載進度,效果圖見最上方