概要
Glide は標準で SVG をサポートしてなかったので試してみました。
基本的にはここに記載されている公式のサンプルソースに書いてあることと同じことをしているだけです。
手順
ライブラリの追加
plugins {
...
id 'com.google.devtools.ksp'
}
android {
...
dependencies {
...
ksp 'com.github.bumptech.glide:ksp:4.15.1'
implementation 'com.caverock:androidsvg:1.4'
}
}
以下のファイルを作成する
SvgDecoder.kt
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.ResourceDecoder
import com.bumptech.glide.load.engine.Resource
import com.bumptech.glide.load.resource.SimpleResource
import com.bumptech.glide.request.target.Target
import com.caverock.androidsvg.SVG
import com.caverock.androidsvg.SVGParseException
import java.io.IOException
import java.io.InputStream
/** Decodes an SVG internal representation from an [InputStream]. */
class SvgDecoder : ResourceDecoder<InputStream, SVG> {
override fun handles(source: InputStream, options: Options): Boolean {
return true
}
@Throws(IOException::class)
override fun decode(source: InputStream, width: Int, height: Int, options: Options): Resource<SVG> {
return try {
val svg = SVG.getFromInputStream(source)
if (width != Target.SIZE_ORIGINAL) {
svg.documentWidth = width.toFloat()
}
if (height != Target.SIZE_ORIGINAL) {
svg.documentHeight = height.toFloat()
}
SimpleResource(svg)
} catch (ex: Throwable) {
throw IOException("Cannot load SVG from stream", ex)
}
}
}
SvgDrawableTranscoder.kt
import android.graphics.Picture
import android.graphics.drawable.PictureDrawable
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.engine.Resource
import com.bumptech.glide.load.resource.SimpleResource
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder
import com.caverock.androidsvg.SVG
/**
* Convert the [SVG]'s internal representation to an Android-compatible one ([Picture]).
*/
class SvgDrawableTranscoder : ResourceTranscoder<SVG, PictureDrawable> {
override fun transcode(toTranscode: Resource<SVG>, options: Options): Resource<PictureDrawable> {
val svg = toTranscode.get()
val picture = svg.renderToPicture()
val drawable = PictureDrawable(picture)
return SimpleResource(drawable)
}
}
SvgModule.kt
import android.content.Context
import android.graphics.drawable.PictureDrawable
import com.bumptech.glide.Glide
import com.bumptech.glide.Registry
import com.bumptech.glide.annotation.GlideModule
import com.bumptech.glide.module.AppGlideModule
import com.caverock.androidsvg.SVG
import java.io.InputStream
/** Module for the SVG sample app. */
@GlideModule
class SvgModule : AppGlideModule() {
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
registry.register(SVG::class.java, PictureDrawable::class.java, SvgDrawableTranscoder())
.append(InputStream::class.java, SVG::class.java, SvgDecoder())
}
// Disable manifest parsing to avoid adding similar modules twice.
override fun isManifestParsingEnabled(): Boolean {
return false
}
}
あとは使うだけ
Glide.with(context).load("path/to/svg.svg").into(myView)
GlideImage(model = "path/to/svg.svg",contentDescription = "") // Jetpack Compose
公式のソースとの違い
SVG.getFromInputStream の例外を catch (ex: Throwable) として全て catch するようにしているのが公式との違いです。androidsvg は様々な例外を返すので、あまり行儀が良くないSVGファイルを渡すと元のコードではクラッシュすることがあります。