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