1
+ package com.bagi.drawpath
2
+
3
+ import android.animation.ObjectAnimator
4
+ import android.content.Context
5
+ import android.content.res.Resources
6
+ import android.graphics.*
7
+ import android.util.AttributeSet
8
+ import android.view.View
9
+ import com.bagi.drawpath.DrawerPathView.UiUtils.px
10
+ import com.bvtech.toolslibrary.R
11
+ import kotlin.math.max
12
+
13
+ class DrawerPathView : View {
14
+ private var path: Path ? = null
15
+ private var paint: Paint ? = null
16
+ private var length = 0f
17
+ private var roundCorner = 28
18
+ private var paddingRectangleFromEdge = 5f
19
+ private var animatorDuration = 6000
20
+ private var colorPath = 0xff000000 .toInt()
21
+
22
+ constructor (context: Context ? ) : super (context) {}
23
+ constructor (context: Context ? , attrs: AttributeSet ? ) : super (context, attrs) {
24
+ initAttrs(attrs)
25
+ }
26
+
27
+ constructor (context: Context ? , attrs: AttributeSet ? , defStyleAttr: Int ) : super (
28
+ context,
29
+ attrs,
30
+ defStyleAttr
31
+ ) {
32
+ initAttrs(attrs)
33
+ }
34
+
35
+ private fun initAttrs (attrs : AttributeSet ? ) {
36
+ val arr = context.obtainStyledAttributes(attrs, R .styleable.WidgetAttributes )
37
+ arr.let {
38
+ paddingRectangleFromEdge =
39
+ it.getFloat(R .styleable.WidgetAttributes_paddingRectangleFromEdge , 5f )
40
+ animatorDuration = it.getInt(R .styleable.WidgetAttributes_animatorDurationSec , 6 )
41
+ roundCorner = it.getInt(R .styleable.WidgetAttributes_roundCornerInPx , 28 )
42
+ colorPath = it.getColor(R .styleable.WidgetAttributes_colorPath , 0xff000000 .toInt())
43
+ }
44
+ arr.recycle()
45
+ }
46
+
47
+ fun init (widthRec : Int , heightRec : Int ) {
48
+ setPaint()
49
+ setPathToDraw(widthRec, heightRec)
50
+ setAnimator()
51
+ }
52
+
53
+ private fun setAnimator () {
54
+ // Measure the path
55
+ val measure = PathMeasure (path, false )
56
+ length = measure.length
57
+ val animator = ObjectAnimator .ofFloat(this @DrawerPathView, " phase" , 1.0f , 0.0f )
58
+ animator.duration = animatorDuration.times(1000 ).toLong()
59
+ animator.start()
60
+ }
61
+
62
+ // is called by animator object "propertyName" parameter
63
+ fun setPhase (phase : Float ) {
64
+ paint?.pathEffect = createPathEffect(length, phase, 0.0f )
65
+ invalidate()
66
+ }
67
+
68
+ private fun createPathEffect (pathLength : Float , phase : Float , offset : Float ) =
69
+ DashPathEffect (
70
+ floatArrayOf(pathLength, pathLength),
71
+ max(phase * pathLength, offset)
72
+ )
73
+
74
+
75
+ private fun setPathToDraw (widthRec : Int , heightRec : Int ) {
76
+ path = Path ()
77
+ val rectF = RectF (
78
+ paddingRectangleFromEdge,
79
+ paddingRectangleFromEdge,
80
+ (widthRec - paddingRectangleFromEdge),
81
+ (heightRec - paddingRectangleFromEdge)
82
+ )
83
+ path?.addRoundRect(rectF, roundCorner.toFloat().px.toFloat(), roundCorner.toFloat().px.toFloat(), Path .Direction .CW )
84
+ }
85
+
86
+ private fun setPaint () {
87
+ paint = Paint ()
88
+ paint?.color = colorPath
89
+ paint?.strokeWidth = 5f
90
+ paint?.style = Paint .Style .STROKE
91
+ paint?.isAntiAlias = true
92
+ }
93
+
94
+ public override fun onDraw (c : Canvas ) {
95
+ super .onDraw(c)
96
+ path?.let { pathT ->
97
+ paint?.let { paintT -> c.drawPath(pathT, paintT) }
98
+ }
99
+ }
100
+
101
+ object UiUtils {
102
+ val Float .dp: Int get() = (this / Resources .getSystem().displayMetrics.density).toInt()
103
+ val Float .px: Int get() = (this * Resources .getSystem().displayMetrics.density).toInt()
104
+ fun getWidthDisplayScreenSize () = Resources .getSystem().displayMetrics.widthPixels
105
+ }
106
+ }
0 commit comments