-
Notifications
You must be signed in to change notification settings - Fork 638
/
ScaleDrawable.kt
119 lines (91 loc) · 3.57 KB
/
ScaleDrawable.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package coil.drawable
import android.content.res.ColorStateList
import android.graphics.BlendMode
import android.graphics.Canvas
import android.graphics.ColorFilter
import android.graphics.PorterDuff
import android.graphics.Rect
import android.graphics.drawable.Animatable
import android.graphics.drawable.AnimatedImageDrawable
import android.graphics.drawable.Drawable
import androidx.annotation.RequiresApi
import androidx.core.graphics.withSave
import coil.decode.DecodeUtils
import coil.size.Scale
import kotlin.math.roundToInt
/**
* A [Drawable] that centers and scales its [child] to fill its bounds.
*
* This allows drawables that only draw within their intrinsic dimensions
* (e.g. [AnimatedImageDrawable]) to fill their entire bounds.
*/
class ScaleDrawable @JvmOverloads constructor(
val child: Drawable,
val scale: Scale = Scale.FIT
) : Drawable(), Drawable.Callback, Animatable {
private var childDx = 0f
private var childDy = 0f
private var childScale = 1f
init {
child.callback = this
}
override fun draw(canvas: Canvas) {
canvas.withSave {
translate(childDx, childDy)
scale(childScale, childScale)
child.draw(this)
}
}
override fun getAlpha() = child.alpha
override fun setAlpha(alpha: Int) {
child.alpha = alpha
}
@Deprecated("Deprecated in Java")
@Suppress("DEPRECATION")
override fun getOpacity() = child.opacity
override fun getColorFilter() = child.colorFilter
override fun setColorFilter(colorFilter: ColorFilter?) {
child.colorFilter = colorFilter
}
override fun onBoundsChange(bounds: Rect) {
val width = child.intrinsicWidth
val height = child.intrinsicHeight
if (width <= 0 || height <= 0) {
child.bounds = bounds
childDx = 0f
childDy = 0f
childScale = 1f
return
}
val targetWidth = bounds.width()
val targetHeight = bounds.height()
val multiplier = DecodeUtils.computeSizeMultiplier(width, height, targetWidth, targetHeight, scale)
val left = ((targetWidth - multiplier * width) / 2).roundToInt()
val top = ((targetHeight - multiplier * height) / 2).roundToInt()
val right = left + width
val bottom = top + height
child.setBounds(left, top, right, bottom)
childDx = bounds.left.toFloat()
childDy = bounds.top.toFloat()
childScale = multiplier.toFloat()
}
override fun onLevelChange(level: Int) = child.setLevel(level)
override fun onStateChange(state: IntArray) = child.setState(state)
override fun getIntrinsicWidth() = child.intrinsicWidth
override fun getIntrinsicHeight() = child.intrinsicHeight
override fun unscheduleDrawable(who: Drawable, what: Runnable) = unscheduleSelf(what)
override fun invalidateDrawable(who: Drawable) = invalidateSelf()
override fun scheduleDrawable(who: Drawable, what: Runnable, `when`: Long) = scheduleSelf(what, `when`)
override fun setTint(tintColor: Int) = child.setTint(tintColor)
override fun setTintList(tint: ColorStateList?) = child.setTintList(tint)
override fun setTintMode(tintMode: PorterDuff.Mode?) = child.setTintMode(tintMode)
@RequiresApi(29)
override fun setTintBlendMode(blendMode: BlendMode?) = child.setTintBlendMode(blendMode)
override fun isRunning() = child is Animatable && child.isRunning
override fun start() {
if (child is Animatable) child.start()
}
override fun stop() {
if (child is Animatable) child.stop()
}
}