improve animation performance

This commit is contained in:
Johan von Forstner
2020-04-12 19:37:01 +02:00
parent e20dbd6ec1
commit 04fef1e5d2
3 changed files with 44 additions and 28 deletions

View File

@@ -302,10 +302,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
MarkerOptions()
.position(LatLng(charger.coordinates.lat, charger.coordinates.lng))
.icon(
chargerIconGenerator.getBitmapDescriptor(
R.drawable.ic_map_marker_charging,
tint
)
chargerIconGenerator.getBitmapDescriptor(tint)
)
)
animateMarkerAppear(marker, tint, chargerIconGenerator)

View File

@@ -5,9 +5,9 @@ import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.PorterDuff
import android.graphics.drawable.Drawable
import android.util.LruCache
import android.view.ViewGroup
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.DrawableCompat
import com.google.android.gms.maps.model.BitmapDescriptor
@@ -40,29 +40,56 @@ class ClusterIconGenerator(context: Context) : IconGenerator(context) {
class ChargerIconGenerator(val context: Context) {
data class BitmapData(val id: Int, val tint: Int, val scale: Int, val alpha: Int)
data class BitmapData(val tint: Int, val scale: Int, val alpha: Int)
val cache = hashMapOf<BitmapData, Bitmap>()
val cacheSize = 4 * 1024 * 1024; // 4MiB
val cache = object : LruCache<BitmapData, Bitmap>(cacheSize) {
override fun sizeOf(key: BitmapData, value: Bitmap): Int {
return value.byteCount
}
}
val oversize = 1.5f
val icon = R.drawable.ic_map_marker_charging
init {
preloadCache()
}
fun preloadCache() {
// pre-generates images for scale from 0 to 255 for all possible tint colors
val tints = listOf(
R.color.charger_100kw,
R.color.charger_43kw,
R.color.charger_20kw,
R.color.charger_11kw,
R.color.charger_low
)
for (tint in tints) {
for (scale in 0..20) {
val data = BitmapData(tint, scale, 255)
cache.put(data, generateBitmap(data))
}
}
}
fun getBitmapDescriptor(
@DrawableRes id: Int,
@ColorRes tint: Int,
scale: Int = 255,
scale: Int = 20,
alpha: Int = 255
): BitmapDescriptor? {
val data = BitmapData(id, tint, scale, alpha)
if (cache.containsKey(data)) {
return BitmapDescriptorFactory.fromBitmap(cache[data])
val data = BitmapData(tint, scale, alpha)
val cachedImg = cache[data]
return if (cachedImg != null) {
BitmapDescriptorFactory.fromBitmap(cachedImg)
} else {
val bitmap = generateBitmap(data)
cache[data] = bitmap
return BitmapDescriptorFactory.fromBitmap(bitmap)
cache.put(data, bitmap)
BitmapDescriptorFactory.fromBitmap(bitmap)
}
}
private fun generateBitmap(data: BitmapData): Bitmap {
val vd: Drawable = context.getDrawable(data.id)!!
val vd: Drawable = context.getDrawable(icon)!!
DrawableCompat.setTint(vd, ContextCompat.getColor(context, data.tint));
DrawableCompat.setTintMode(vd, PorterDuff.Mode.MULTIPLY);
@@ -82,7 +109,7 @@ class ChargerIconGenerator(val context: Context) {
)
val canvas = Canvas(bm)
val scale = data.scale / 255f
val scale = data.scale / 20f
canvas.scale(
scale,
scale,

View File

@@ -21,7 +21,7 @@ fun animateMarkerAppear(
tint: Int,
gen: ChargerIconGenerator
) {
ValueAnimator.ofInt(0, 255).apply {
ValueAnimator.ofInt(0, 20).apply {
duration = 250
interpolator = LinearOutSlowInInterpolator()
addUpdateListener { animationState ->
@@ -31,11 +31,7 @@ fun animateMarkerAppear(
}
val scale = animationState.animatedValue as Int
marker.setIcon(
gen.getBitmapDescriptor(
R.drawable.ic_map_marker_charging,
tint,
scale = scale
)
gen.getBitmapDescriptor(tint, scale = scale)
)
}
}.start()
@@ -46,7 +42,7 @@ fun animateMarkerDisappear(
tint: Int,
gen: ChargerIconGenerator
) {
ValueAnimator.ofInt(255, 0).apply {
ValueAnimator.ofInt(20, 0).apply {
duration = 200
interpolator = FastOutLinearInInterpolator()
addUpdateListener { animationState ->
@@ -56,11 +52,7 @@ fun animateMarkerDisappear(
}
val scale = animationState.animatedValue as Int
marker.setIcon(
gen.getBitmapDescriptor(
R.drawable.ic_map_marker_charging,
tint,
scale = scale
)
gen.getBitmapDescriptor(tint, scale = scale)
)
}
addListener(onEnd = {