package com.svgurl import android.content.Context import android.graphics.drawable.PictureDrawable import androidx.appcompat.widget.AppCompatImageView import com.caverock.androidsvg.SVG import kotlinx.coroutines.* import java.io.File import java.io.FileOutputStream import java.net.URL import java.security.MessageDigest import android.util.LruCache import android.view.ViewGroup.LayoutParams class SvgUrlView(context: Context) : AppCompatImageView(context) { companion object { private val memoryCache = object : LruCache(50) {} private fun getCacheDir(context: Context): File { val dir = File(context.cacheDir, "svg_cache") if (!dir.exists()) dir.mkdirs() return dir } private fun getCacheFile(context: Context, url: String): File { val hash = url.md5() return File(getCacheDir(context), "$hash.svg") } private fun String.md5(): String { val bytes = MessageDigest.getInstance("MD5").digest(toByteArray()) return bytes.joinToString("") { "%02x".format(it) } } } private var currentJob: Job? = null fun setUrl(url: String) { currentJob?.cancel() currentJob = CoroutineScope(Dispatchers.IO).launch { try { // Memory cache first memoryCache.get(url)?.let { cached -> withContext(Dispatchers.Main) { setLayerType(LAYER_TYPE_SOFTWARE, null) scaleType = ScaleType.FIT_CENTER setImageDrawable(cached) } return@launch } val cacheFile = getCacheFile(context, url) val inputStream = if (cacheFile.exists()) { cacheFile.inputStream() } else { val bytes = URL(url).openStream().readBytes() FileOutputStream(cacheFile).use { it.write(bytes) } cacheFile.inputStream() } val svg = SVG.getFromInputStream(inputStream) val drawable = PictureDrawable(svg.renderToPicture()) memoryCache.put(url, drawable) withContext(Dispatchers.Main) { setLayerType(LAYER_TYPE_SOFTWARE, null) scaleType = ScaleType.FIT_CENTER setImageDrawable(drawable) } } catch (e: Exception) { e.printStackTrace() } } } fun setWidthProp(width: Int) { layoutParams = layoutParams ?: LayoutParams(width, LayoutParams.WRAP_CONTENT) layoutParams.width = width requestLayout() } fun setHeightProp(height: Int) { layoutParams = layoutParams ?: LayoutParams(LayoutParams.WRAP_CONTENT, height) layoutParams.height = height requestLayout() } override fun onDetachedFromWindow() { super.onDetachedFromWindow() currentJob?.cancel() } public fun setShowSkeleton(show: Boolean) { } public fun setPlaceholder(uri: String?) { } public fun setFailedPlaceholder(uri: String?) { } }