@@ -14,8 +14,11 @@ import android.graphics.Rect
14
14
import android.graphics.RectF
15
15
import android.graphics.Shader
16
16
import android.graphics.SweepGradient
17
+ import android.graphics.drawable.Drawable
17
18
import android.graphics.drawable.GradientDrawable
19
+ import android.os.Build
18
20
import android.util.AttributeSet
21
+ import android.util.Log
19
22
import android.util.TypedValue
20
23
import androidx.core.content.res.TypedArrayUtils.obtainAttributes
21
24
import androidx.core.graphics.ColorUtils
@@ -30,28 +33,34 @@ import com.google.android.material.shape.RelativeCornerSize
30
33
import com.google.android.material.shape.RoundedCornerTreatment
31
34
import com.google.android.material.shape.ShapeAppearanceModel
32
35
import com.google.android.material.shape.ShapeAppearancePathProvider
33
- import me.reezy.cosmo.R
34
36
import org.xmlpull.v1.XmlPullParser
35
37
import kotlin.math.PI
36
38
import kotlin.math.atan
37
39
import kotlin.math.min
38
40
import kotlin.math.sqrt
39
41
42
+ @Suppress(" NOTHING_TO_INLINE" )
40
43
@SuppressLint(" RestrictedApi" )
41
- class ShapeableDrawable (shapeModel : ShapeAppearanceModel ) : MaterialShapeDrawable(shapeModel) {
44
+ class ShapeableDrawable private constructor(state : ShapeableState , msdState : MaterialShapeDrawableState , isNew : Boolean = true ) : MaterialShapeDrawable(msdState) {
45
+
46
+ private var constantState: RealConstantState = RealConstantState (state, msdState)
47
+
48
+ private val clipRect: RectF = RectF ()
49
+
50
+ val clipPath = Path ()
51
+
42
52
init {
43
53
fieldShadowRenderer.set(this , RealShadowRenderer ())
44
- shadowCompatibilityMode = SHADOW_COMPAT_MODE_ALWAYS
45
- setUseTintColorForShadow(true )
46
- tintList = ColorStateList .valueOf(Color .TRANSPARENT )
54
+ if (isNew) {
55
+ shadowCompatibilityMode = SHADOW_COMPAT_MODE_ALWAYS
56
+ setUseTintColorForShadow(true )
57
+ tintList = ColorStateList .valueOf(Color .TRANSPARENT )
58
+ }
47
59
}
48
60
49
- val clipPath = Path ()
50
-
51
- private val clipRect: RectF = RectF ()
52
- private val gradientState = GradientState ()
61
+ constructor () : this (ShapeableState (), MaterialShapeDrawableState (ShapeAppearanceModel (), null ))
53
62
54
- constructor () : this (ShapeAppearanceModel ( ))
63
+ constructor (shapeModel : ShapeAppearanceModel ) : this (ShapeableState (), MaterialShapeDrawableState (shapeModel, null ))
55
64
56
65
constructor (context: Context , attrs: AttributeSet ? = null , defStyleAttr: Int = 0 , defStyleRes: Int = 0 )
57
66
: this (ShapeAppearanceModel .builder(context, attrs, defStyleAttr, defStyleRes).build()) {
@@ -69,8 +78,22 @@ class ShapeableDrawable(shapeModel: ShapeAppearanceModel) : MaterialShapeDrawabl
69
78
ta.recycle()
70
79
}
71
80
81
+ override fun getIntrinsicWidth (): Int = shapeableState.width
82
+ override fun getIntrinsicHeight (): Int = shapeableState.height
83
+ override fun getConstantState (): ConstantState = constantState
84
+
85
+ override fun mutate (): Drawable {
86
+ super .mutate()
87
+ constantState = RealConstantState (ShapeableState (shapeableState), super .getConstantState() as MaterialShapeDrawableState )
88
+ return this
89
+ }
90
+
91
+ private val shapeableState: ShapeableState get() = constantState.shapeable
72
92
73
93
private fun initAttrs (a : TypedArray ) {
94
+
95
+ shapeableState.init (a)
96
+
74
97
strokeColor = a.getColorStateList(R .styleable.ShapeableDrawable_strokeColor )
75
98
strokeWidth = a.getDimensionPixelSize(R .styleable.ShapeableDrawable_strokeWidth , 0 ).toFloat()
76
99
@@ -81,17 +104,16 @@ class ShapeableDrawable(shapeModel: ShapeAppearanceModel) : MaterialShapeDrawabl
81
104
setCorners(cornerPosition, cornerSize, cornerType)
82
105
}
83
106
84
- // 渐变背景色
85
- gradientState.loadFromAttrs(a)
86
107
87
- if (gradientState .gradientColors != null ) {
108
+ if (shapeableState .gradientColors != null ) {
88
109
setUseTintColorForShadow(false )
89
110
tintList = null
90
111
} else {
91
112
setUseTintColorForShadow(true )
92
113
tintList = a.getColorStateList(R .styleable.ShapeableDrawable_backgroundTint ) ? : ColorStateList .valueOf(Color .TRANSPARENT )
93
114
}
94
115
116
+
95
117
// 阴影
96
118
if (a.hasValue(R .styleable.ShapeableDrawable_shadowRadius )) {
97
119
shadowRadius = a.getDimensionPixelSize(R .styleable.ShapeableDrawable_shadowRadius , 0 )
@@ -198,10 +220,11 @@ class ShapeableDrawable(shapeModel: ShapeAppearanceModel) : MaterialShapeDrawabl
198
220
}
199
221
200
222
override fun onBoundsChange (bounds : Rect ) {
223
+ Log .e(" OoO" , " ${hashCode()} .onBoundsChange($bounds ) width = ${shapeableState.width} " )
201
224
super .onBoundsChange(bounds)
202
225
updateClipPath(bounds.width(), bounds.height())
203
226
204
- gradientState .createFillShader(bounds.toRectF())?.let {
227
+ shapeableState .createFillShader(bounds.toRectF())?.let {
205
228
(fieldFillPaint.get(this ) as Paint ).shader = it
206
229
}
207
230
invalidateSelf()
@@ -234,8 +257,11 @@ class ShapeableDrawable(shapeModel: ShapeAppearanceModel) : MaterialShapeDrawabl
234
257
}
235
258
236
259
260
+ private class ShapeableState () {
261
+
237
262
238
- private class GradientState {
263
+ var width: Int = - 1
264
+ var height: Int = - 1
239
265
240
266
var gradientColors: IntArray? = null
241
267
var gradientType: Int = GradientDrawable .LINEAR_GRADIENT
@@ -244,7 +270,22 @@ class ShapeableDrawable(shapeModel: ShapeAppearanceModel) : MaterialShapeDrawabl
244
270
var gradientCenterY: Float = 0.5f
245
271
var gradientRadius: Float = 0.5f
246
272
247
- fun loadFromAttrs (a : TypedArray ) {
273
+ constructor (orig: ShapeableState ) : this () {
274
+ width = orig.width
275
+ height = orig.height
276
+
277
+ gradientColors = orig.gradientColors
278
+ gradientType = orig.gradientType
279
+ gradientOrientation = orig.gradientOrientation
280
+ gradientCenterX = orig.gradientCenterX
281
+ gradientCenterY = orig.gradientCenterY
282
+ gradientRadius = orig.gradientRadius
283
+ }
284
+
285
+
286
+ fun init (a : TypedArray ) {
287
+ width = a.getDimensionPixelSize(R .styleable.ShapeableDrawable_android_width , - 1 )
288
+ height = a.getDimensionPixelSize(R .styleable.ShapeableDrawable_android_height , - 1 )
248
289
249
290
gradientColors = a.getGradientColors()
250
291
gradientType = a.getInt(R .styleable.ShapeableDrawable_gradientType , GradientDrawable .LINEAR_GRADIENT )
@@ -257,6 +298,7 @@ class ShapeableDrawable(shapeModel: ShapeAppearanceModel) : MaterialShapeDrawabl
257
298
GradientDrawable .Orientation .TOP_BOTTOM
258
299
}
259
300
}
301
+
260
302
fun createFillShader (rect : RectF ): Shader ? = when {
261
303
gradientColors == null -> null
262
304
gradientType == GradientDrawable .LINEAR_GRADIENT -> {
@@ -270,7 +312,12 @@ class ShapeableDrawable(shapeModel: ShapeAppearanceModel) : MaterialShapeDrawabl
270
312
GradientDrawable .Orientation .LEFT_RIGHT -> RectF (rect.left, rect.top, rect.right, rect.top)
271
313
else -> RectF (rect.left, rect.top, rect.right, rect.bottom)
272
314
}
273
- LinearGradient (r.left, r.top, r.right, r.bottom, gradientColors!! , null , Shader .TileMode .CLAMP )
315
+ val tileMode = if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .S ) {
316
+ Shader .TileMode .DECAL
317
+ } else {
318
+ Shader .TileMode .CLAMP
319
+ }
320
+ LinearGradient (r.left, r.top, r.right, r.bottom, gradientColors!! , null , tileMode)
274
321
}
275
322
276
323
gradientType == GradientDrawable .RADIAL_GRADIENT -> {
@@ -306,6 +353,18 @@ class ShapeableDrawable(shapeModel: ShapeAppearanceModel) : MaterialShapeDrawabl
306
353
}
307
354
return null
308
355
}
356
+
357
+ }
358
+
359
+
360
+ private class RealConstantState (val shapeable : ShapeableState , val msd : MaterialShapeDrawableState ) : ConstantState() {
361
+ override fun newDrawable (): Drawable {
362
+ val d = ShapeableDrawable (ShapeableState (shapeable), msd, false )
363
+ d.invalidateSelf()
364
+ return d
365
+ }
366
+
367
+ override fun getChangingConfigurations (): Int = 0
309
368
}
310
369
311
370
private class RealShadowRenderer : ShadowRenderer () {
0 commit comments