java - ¿Glide tiene un método para cargar PNG y SVG?
android android-glide (2)
Estoy usando
Glide
para cargar algunas imágenes de
forma asíncrona
en algunos de mis
ImageView
s, y sé que puede manejar imágenes como
PNG
o
JPG
ya que puede manejar
SVG
.
La cosa es que, hasta donde yo sé, la forma en que cargo esos dos tipos de imagen es diferente. Me gusta:
Cargando imágenes "normales"
Glide.with(mContext)
.load("URL")
.into(cardHolder.iv_card);
Cargando SVG
GenericRequestBuilder<Uri, InputStream, SVG, PictureDrawable> requestBuilder = Glide.with(mContext)
.using(Glide.buildStreamModelLoader(Uri.class, mContext), InputStream.class)
.from(Uri.class)
.as(SVG.class)
.transcode(new SvgDrawableTranscoder(), PictureDrawable.class)
.sourceEncoder(new StreamEncoder())
.cacheDecoder(new FileToStreamDecoder<>(new SVGDecoder()))
.decoder(new SVGDecoder())
.listener(new SvgSoftwareLayerSetter<Uri>());
requestBuilder
.diskCacheStrategy(DiskCacheStrategy.NONE)
.load(Uri.parse("URL"))
.into(cardHolder.iv_card);
Y si trato de cargar SVG con el primer método, no funcionará. Si intento cargar PNG o JPG con el segundo método, tampoco funcionará.
¿Hay alguna forma genérica de cargar ambos tipos de imágenes con Glide?
El servidor del que estoy obteniendo esas imágenes no me dice el tipo de imagen antes de descargarla.
Es un servidor REST y el recurso se recuperará de forma similar a
"http://foo.bar/resource"
.
La única forma de saber el tipo de imagen es leer la respuesta HEAD.
Agregué una tubería de decodificación flexible para decodificar una imagen o SVG, ¡tal vez pueda ayudar! basado en el ejemplo de deslizamiento SVG
Descifrador
class SvgOrImageDecoder : ResourceDecoder<InputStream, SvgOrImageDecodedResource> {
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<SvgOrImageDecodedResource>? {
val array = source.readBytes()
val svgInputStream = ByteArrayInputStream(array.clone())
val pngInputStream = ByteArrayInputStream(array.clone())
return try {
val svg = SVG.getFromInputStream(svgInputStream)
try {
source.close()
pngInputStream.close()
} catch (e: IOException) {}
SimpleResource(SvgOrImageDecodedResource(svg))
} catch (ex: SVGParseException) {
try {
val bitmap = BitmapFactory.decodeStream(pngInputStream)
SimpleResource(SvgOrImageDecodedResource(bitmap = bitmap))
} catch (exception: Exception){
try {
source.close()
pngInputStream.close()
} catch (e: IOException) {}
throw IOException("Cannot load SVG or Image from stream", ex)
}
}
}
Transcodificador
class SvgOrImageDrawableTranscoder : ResourceTranscoder<SvgOrImageDecodedResource, PictureDrawable> {
override fun transcode(
toTranscode: Resource<SvgOrImageDecodedResource>,
options: Options
): Resource<PictureDrawable>? {
val data = toTranscode.get()
if (data.svg != null) {
val picture = data.svg.renderToPicture()
val drawable = PictureDrawable(picture)
return SimpleResource(drawable)
} else if (data.bitmap != null)
return SimpleResource(PictureDrawable(renderToPicture(data.bitmap)))
else return null
}
private fun renderToPicture(bitmap: Bitmap): Picture{
val picture = Picture()
val canvas = picture.beginRecording(bitmap.width, bitmap.height)
canvas.drawBitmap(bitmap, null, RectF(0f, 0f, bitmap.width.toFloat(), bitmap.height.toFloat()), null)
picture.endRecording();
return picture
}
Recurso Decodificado
data class SvgOrImageDecodedResource(
val svg:SVG? = null,
val bitmap: Bitmap? = null)
Módulo de deslizamiento
class AppGlideModule : AppGlideModule() {
override fun registerComponents(
context: Context, glide: Glide, registry: Registry
) {
registry.register(SvgOrImageDecodedResource::class.java, PictureDrawable::class.java, SvgOrImageDrawableTranscoder())
.append(InputStream::class.java, SvgOrImageDecodedResource::class.java, SvgOrImageDecoder())
}
// Disable manifest parsing to avoid adding similar modules twice.
override fun isManifestParsingEnabled(): Boolean {
return false
}
}
Puede usar Glide y AndroidSVG juntos para lograr su objetivo.
Hay una muestra de Glide para SVG. Ejemplo de muestra
Configurar RequestBuilder
requestBuilder = Glide.with(mActivity)
.using(Glide.buildStreamModelLoader(Uri.class, mActivity), InputStream.class)
.from(Uri.class)
.as(SVG.class)
.transcode(new SvgDrawableTranscoder(), PictureDrawable.class)
.sourceEncoder(new StreamEncoder())
.cacheDecoder(new FileToStreamDecoder<SVG>(new SvgDecoder()))
.decoder(new SvgDecoder())
.placeholder(R.drawable.ic_facebook)
.error(R.drawable.ic_web)
.animate(android.R.anim.fade_in)
.listener(new SvgSoftwareLayerSetter<Uri>());
Use RequestBuilder con uri
Uri uri = Uri.parse("http://upload.wikimedia.org/wikipedia/commons/e/e8/Svg_example3.svg");
requestBuilder
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
// SVG cannot be serialized so it''s not worth to cache it
.load(uri)
.into(mImageView);
De esta manera puedes lograr tu objetivo. Espero que esto sea útil.