寫程式久了, 一定會碰到官方提供的view不夠, 需要自己客製化View的時候
最簡單的就是button啊 switch啊 textview等小東西font 或著 style 調整,
但若有點複雜怎麼辦, 最直接最快的方式就是去找library, 感覺就使用了黑科技一般, 一個瞬間就搞定
但要更改的時候, 卻會麻煩的要死, 問題多多...
這邊來介紹create widget 啊
身為Android 開發人員, 這部分一定要懂的拉
圓形progress 其實概念很簡單
就是在view 上面畫兩個東西
1 背景的環
2. progress 的線段
若要額外顯示 progress value 則再加個 text
若是新手看這篇的話,應該會有很多物件疑問。若看不懂的話,就自己再去查吧XD
這裡已算是客製化view的範疇
提個基本概念,若要在view中呈現任何東西的話,一定要在onDraw中把東西畫出來。
這時一定會用到
Canvas: 畫布
Paint: 畫筆
這兩個相關用法,這裡只提相關的,其他請自行爬文去
不囉說,先放成果圖
RingProgress View
首先建立一個 可以放在layout中的 custom view
class RingProgressBar @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : View(context, attrs, defStyleAttr) { ... }
@JvmOverloads 是kotlin 給java 多載的方法
可當作
class RingProgressBar : View { constructor(context: Context) constructor(context: Context, attrs: AttributeSet) constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) ... }
Init Paint
我們需要三個paint , 分別代表
Text Paint (textPaint)
RingBackground Paint(bgPaint)
Progress paint (paint)
private val textPaint = Paint().apply { this.isAntiAlias = true style = Paint.Style.FILL } private val paint: Paint = Paint().apply { isAntiAlias = true style = Paint.Style.STROKE strokeCap = Paint.Cap.ROUND } private val bgPaint: Paint = Paint().apply { isAntiAlias = true style = Paint.Style.STROKE strokeCap = Paint.Cap.ROUND }
Paint.Style.STROKE : 只畫邊框,沒有填滿
isAntiAlias:防鋸齒
strokeCap: 筆頭樣式, 設為圓頭
paint color 與 strokewidth (筆頭的寬?) 請自行定義
Get layour width and height
onSizeChanged中 便可取得layout改變得值 (ex:swithc Portrait / Landscape )
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) Log.d("RingProgressBar", "onSizeChanged") centerW = w / 2f centerH = h / 2f radius = min(centerW, centerH) - radiusOffset rectF.apply { left = radiusOffset top = h / 2 - radius right = w - radiusOffset bottom = h / 2 + radius } }
rectF 為 RectF物件,用來方便紀錄範圍
onDraw
Progress 以逆時鐘方式長出, 所以 startArc 為 (1 - progressValue.toFloat() / max) * 359f
若想要順時鐘長出改為 startArc 為 (progressValue.toFloat() / max) * 359f, 並在起時位置設為 270
override fun onDraw(canvas: Canvas) { super.onDraw(canvas) Log.d("RingProgressBar", "onDraw") with(canvas) { // add bg drawCircle(centerW, centerH, radius, bgPaint) // progress val startArc = (1 - progressValue.toFloat() / max) * 359f drawArc(rectF, 270f + startArc, 359f - startArc, false, paint) // progress text val text = "$progressValue%" textPaint.getTextBounds(text, 0, text.length, textRect) val posX = width / 2 - textRect.width() / 2f - textRect.left val posY = height / 2 - textRect.height() / 2f - textRect.top drawText(text, posX, posY, textPaint) } }
drawCircle 畫出 背景圓環
drawArc 畫出 progress 線段
drawText 畫出文字
範例 link : https://gitlab.com/jc7003/ringprogress
本範例使用 attr 方式,便可在layout中定義相關 attr 自定義 可看這篇 View Attribute
留言列表