@@ -7,34 +7,21 @@ import android.graphics.Color
7
7
import android.graphics.Paint
8
8
import android.graphics.Rect
9
9
import android.graphics.RectF
10
- import android.os.Handler
11
- import android.os.Message
12
10
import android.text.TextPaint
13
11
import android.util.AttributeSet
14
12
import android.view.View
15
- import androidx.annotation.ColorInt
16
13
import com.pengxh.kt.lite.R
17
14
import com.pengxh.kt.lite.extensions.dp2px
18
- import com.pengxh.kt.lite.utils.WeakReferenceHandler
19
- import kotlinx.coroutines.CoroutineScope
20
- import kotlinx.coroutines.Dispatchers
21
- import kotlinx.coroutines.delay
22
- import kotlinx.coroutines.launch
23
- import kotlinx.coroutines.withContext
15
+ import com.pengxh.kt.lite.extensions.sp2px
24
16
25
17
/* *
26
18
* 空气污染指数表盘,仿HUAWEI天气
27
19
*
28
20
* binding.airDashBoardView
29
- * .setMaxValue(500)
30
21
* .setCenterText("优")
31
- * .setAirRingForeground(Color.GREEN)
32
- * .setAirCenterTextColor(Color.RED)
33
- * .setAirCurrentValueColor(Color.BLUE)
34
22
* .setCurrentValue(255)
35
23
*/
36
- class AirDashBoardView constructor(context : Context , attrs : AttributeSet ) : View(context, attrs),
37
- Handler .Callback {
24
+ class AirDashBoardView constructor(context : Context , attrs : AttributeSet ) : View(context, attrs) {
38
25
39
26
// View中心X坐标
40
27
private var centerX = 0f
@@ -48,19 +35,17 @@ class AirDashBoardView constructor(context: Context, attrs: AttributeSet) : View
48
35
private val ringRadius: Int
49
36
private lateinit var guidePaint: Paint
50
37
51
- // 表盘圆弧背景色
38
+ // 表盘圆弧色
52
39
private val background: Int
40
+ private val foreground: Int
53
41
private val ringStroke: Int
54
42
private val ringRectF: RectF
55
43
private lateinit var ringPaint: Paint
56
44
57
45
// 阈值
58
- private val thresholdTextSize: Int
59
- private val thresholdColor: Int
60
46
private lateinit var thresholdPaint: TextPaint
61
47
62
- private val weakReferenceHandler by lazy { WeakReferenceHandler (this ) }
63
- private val currentValueTextSize: Int
48
+ private val centerTextColor: Int
64
49
private val centerTextSize: Int
65
50
66
51
// 当前污染物测量值
@@ -76,8 +61,7 @@ class AirDashBoardView constructor(context: Context, attrs: AttributeSet) : View
76
61
private var sweepAngle = 0f
77
62
78
63
// 表盘中心文字
79
- private var centerText = " 未定义"
80
- private lateinit var currentValuePaint: TextPaint
64
+ private var centerText = " ###"
81
65
private lateinit var centerPaint: TextPaint
82
66
private lateinit var forePaint: Paint
83
67
@@ -88,33 +72,27 @@ class AirDashBoardView constructor(context: Context, attrs: AttributeSet) : View
88
72
* getDimensionPixelSize()返回的是实际数值的四舍五入
89
73
* getDimensionPixelOffset返回的是实际数值去掉后面的小数点
90
74
*/
91
- ringRadius = type.getDimensionPixelOffset (
75
+ ringRadius = type.getDimensionPixelSize (
92
76
R .styleable.AirDashBoardView_air_ring_radius , 100 .dp2px(context)
93
77
)
94
- // 需要给外围刻度留位置
95
- viewSideLength = ringRadius + 30 .dp2px(context)
78
+ viewSideLength = ringRadius + 15 .dp2px(context)
96
79
// 辅助框
97
80
viewRect = Rect (- viewSideLength, - viewSideLength, viewSideLength, viewSideLength)
98
81
ringRectF = RectF (
99
82
- ringRadius.toFloat(), - ringRadius.toFloat(), ringRadius.toFloat(), ringRadius.toFloat()
100
83
)
101
84
background = type.getColor(R .styleable.AirDashBoardView_air_ring_background , Color .LTGRAY )
102
- ringStroke = type.getDimensionPixelOffset(
85
+ foreground = type.getColor(R .styleable.AirDashBoardView_air_ring_foreground , Color .BLUE )
86
+ ringStroke = type.getDimensionPixelSize(
103
87
R .styleable.AirDashBoardView_air_ring_stroke , 5 .dp2px(context)
104
88
)
105
89
106
- thresholdTextSize = type.getDimensionPixelOffset (
107
- R .styleable.AirDashBoardView_air_valueSize , 12 .dp2px (context)
90
+ centerTextSize = type.getDimensionPixelSize (
91
+ R .styleable.AirDashBoardView_air_center_text_size , 20 .sp2px (context)
108
92
)
109
- thresholdColor = type.getColor(R .styleable.AirDashBoardView_air_valueColor , Color .LTGRAY )
110
-
111
- currentValueTextSize = type.getDimensionPixelOffset(
112
- R .styleable.AirDashBoardView_air_current_valueSize , 24 .dp2px(context)
113
- )
114
- centerTextSize = type.getDimensionPixelOffset(
115
- R .styleable.AirDashBoardView_air_center_textSize , 12 .dp2px(context)
93
+ centerTextColor = type.getColor(
94
+ R .styleable.AirDashBoardView_air_center_text_color , Color .BLUE
116
95
)
117
-
118
96
type.recycle()
119
97
120
98
// 初始化画笔
@@ -132,32 +110,29 @@ class AirDashBoardView constructor(context: Context, attrs: AttributeSet) : View
132
110
ringPaint.color = background
133
111
ringPaint.strokeCap = Paint .Cap .ROUND
134
112
ringPaint.style = Paint .Style .STROKE
135
- ringPaint.strokeWidth = ringStroke.toFloat().dp2px(context)
113
+ ringPaint.strokeWidth = ringStroke.toFloat()
136
114
ringPaint.isAntiAlias = true
137
- // 设置背景光晕
138
- ringPaint.maskFilter = BlurMaskFilter (15f , BlurMaskFilter .Blur .SOLID )
139
115
140
116
thresholdPaint = TextPaint ()
141
- thresholdPaint.color = thresholdColor
117
+ thresholdPaint.color = Color . DKGRAY
142
118
thresholdPaint.isAntiAlias = true
143
119
thresholdPaint.textAlign = Paint .Align .CENTER
144
- thresholdPaint.textSize = thresholdTextSize.toFloat()
145
-
146
- currentValuePaint = TextPaint ()
147
- currentValuePaint.isAntiAlias = true
148
- currentValuePaint.textAlign = Paint .Align .CENTER
149
- currentValuePaint.textSize = currentValueTextSize.toFloat()
120
+ thresholdPaint.textSize = 16f .dp2px(context)
150
121
151
122
centerPaint = TextPaint ()
123
+ centerPaint.color = centerTextColor
152
124
centerPaint.isAntiAlias = true
153
125
centerPaint.textAlign = Paint .Align .CENTER
154
126
centerPaint.textSize = centerTextSize.toFloat()
155
127
156
128
forePaint = Paint ()
129
+ forePaint.color = foreground
157
130
forePaint.strokeCap = Paint .Cap .ROUND
158
131
forePaint.style = Paint .Style .STROKE
159
- forePaint.strokeWidth = ringStroke.toFloat().dp2px(context)
132
+ forePaint.strokeWidth = ringStroke.toFloat()
160
133
forePaint.isAntiAlias = true
134
+ // 设置背景光晕
135
+ forePaint.maskFilter = BlurMaskFilter (15f , BlurMaskFilter .Blur .SOLID )
161
136
}
162
137
163
138
override fun onSizeChanged (w : Int , h : Int , oldw : Int , oldh : Int ) {
@@ -198,8 +173,8 @@ class AirDashBoardView constructor(context: Context, attrs: AttributeSet) : View
198
173
* 画布移到中心位置,方便绘制一系列图形
199
174
*/
200
175
canvas.translate(centerX, centerY)
201
-
202
176
// drawGuides(canvas)
177
+
203
178
/* *
204
179
* 从左往右画,顺时针,左边是180度
205
180
*/
@@ -296,83 +271,47 @@ class AirDashBoardView constructor(context: Context, attrs: AttributeSet) : View
296
271
}
297
272
298
273
private fun drawMinValue (canvas : Canvas ) {
299
- val fontMetrics = thresholdPaint.fontMetrics
300
- val top = fontMetrics.top
301
- val bottom = fontMetrics.bottom
302
274
canvas.drawText(
303
275
minValue.toString(),
304
276
- viewSideLength / 2f ,
305
- viewSideLength / 2f - (top + bottom) * 2.5f ,
277
+ viewSideLength / 2f + viewSideLength / 3f ,
306
278
thresholdPaint
307
279
)
308
280
}
309
281
310
282
private fun drawMaxValue (canvas : Canvas ) {
311
- val fontMetrics = thresholdPaint.fontMetrics
312
- val top = fontMetrics.top
313
- val bottom = fontMetrics.bottom
314
283
canvas.drawText(
315
284
maxValue.toString(),
316
285
viewSideLength / 2f ,
317
- viewSideLength / 2f - (top + bottom) * 2.5f ,
286
+ viewSideLength / 2f + viewSideLength / 3f ,
318
287
thresholdPaint
319
288
)
320
289
}
321
290
322
291
private fun drawCurrentValue (canvas : Canvas ) {
323
- val fontMetrics = currentValuePaint.fontMetrics
324
- val top = fontMetrics.top
325
- val bottom = fontMetrics.bottom
326
292
canvas.drawText(
327
293
currentValue.toString(),
328
294
0f ,
329
- - (top + bottom) / 2f ,
330
- currentValuePaint
295
+ viewSideLength / 2f - viewSideLength / 3f ,
296
+ centerPaint
331
297
)
332
298
}
333
299
334
300
private fun drawCenterText (canvas : Canvas ) {
335
- val fontMetrics = centerPaint.fontMetrics
336
- val top = fontMetrics.top
337
- val bottom = fontMetrics.bottom
338
301
canvas.drawText(
339
302
centerText,
340
303
0f ,
341
- (top + bottom) * 2 ,
304
+ - viewSideLength / 12f ,
342
305
centerPaint
343
306
)
344
307
}
345
308
346
- fun setMaxValue (maxValue : Int ): AirDashBoardView {
347
- this .maxValue = maxValue
348
- invalidate()
349
- return this
350
- }
351
-
352
309
fun setCenterText (centerText : String ): AirDashBoardView {
353
310
this .centerText = centerText
354
311
invalidate()
355
312
return this
356
313
}
357
314
358
- fun setAirRingForeground (@ColorInt color : Int ): AirDashBoardView {
359
- forePaint.color = color
360
- invalidate()
361
- return this
362
- }
363
-
364
- fun setAirCenterTextColor (@ColorInt color : Int ): AirDashBoardView {
365
- centerPaint.color = color
366
- invalidate()
367
- return this
368
- }
369
-
370
- fun setAirCurrentValueColor (@ColorInt color : Int ): AirDashBoardView {
371
- currentValuePaint.color = color
372
- invalidate()
373
- return this
374
- }
375
-
376
315
fun setCurrentValue (value : Int ) {
377
316
currentValue = if (value < 0 ) {
378
317
0
@@ -382,36 +321,18 @@ class AirDashBoardView constructor(context: Context, attrs: AttributeSet) : View
382
321
value
383
322
}
384
323
385
- CoroutineScope (Dispatchers .Main ).launch {
386
- withContext(Dispatchers .IO ) {
387
- for (i in 0 until currentValue) {
388
- weakReferenceHandler.post(updateProgressRunnable.setProgress(i))
389
- delay(10 )
324
+ val i = intArrayOf(0 )
325
+ post(object : Runnable {
326
+ override fun run () {
327
+ i[0 ]++
328
+ sweepAngle = i[0 ].toFloat() * 270 / maxValue
329
+ invalidate()
330
+ if (i[0 ] <= value) {
331
+ postDelayed(this , 5 )
332
+ } else {
333
+ removeCallbacks(this )
390
334
}
391
335
}
392
- }
393
- }
394
-
395
- private interface UpdateProgressRunnable : Runnable {
396
- fun setProgress (progress : Int ): UpdateProgressRunnable
397
- }
398
-
399
- private val updateProgressRunnable = object : UpdateProgressRunnable {
400
-
401
- private var progress = 0
402
-
403
- override fun setProgress (progress : Int ): UpdateProgressRunnable {
404
- this .progress = progress
405
- return this
406
- }
407
-
408
- override fun run () {
409
- sweepAngle = progress.toFloat() * 270 / maxValue
410
- invalidate()
411
- }
412
- }
413
-
414
- override fun handleMessage (msg : Message ): Boolean {
415
- return true
336
+ })
416
337
}
417
338
}
0 commit comments