【问题标题】:Does Glide have a method for loading both PNG and SVG?Glide 有加载 PNG 和 SVG 的方法吗?
【发布时间】:2016-06-01 04:17:42
【问题描述】:

我正在使用Glide 将一些图像异步加载到我的一些ImageViews 中,我知道它可以处理像PNGJPG 这样的图像,因为它可以处理SVG

据我所知,我加载这两种图像的方式不同。喜欢:

加载“正常”图像

Glide.with(mContext)
                .load("URL")
                .into(cardHolder.iv_card);

加载 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);

如果我尝试使用第一种方法加载 SVG,它将无法正常工作。如果我尝试用第二种方法加载 PNG 或 JPG,它也不起作用。

是否有一种通用的方法可以使用 Glide 加载这两种图像类型?

我从中获取这些图像的服务器在我下载之前不会告诉我图像类型。它是一个 REST 服务器,资源将以"http://foo.bar/resource" 之类的方式检索。了解图像类型的唯一方法是读取 HEAD 响应。

【问题讨论】:

  • 您可能想澄清一下是什么意思,否则就不行了
  • 我已经编辑了我的问题。

标签: java android svg android-glide


【解决方案1】:

您可以同时使用GlideAndroidSVG 来实现您的目标。

有来自 Glide 的 SVG 示例。Sample Example

设置 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>());

将 RequestBuilder 与 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);

这样你就可以实现你的目标。我希望这会有所帮助。

【讨论】:

  • 这正是我加载 SVG 的方式。但我事先不知道图像是 SVG 还是 PNG。所以加载可能会失败。
  • 从 URL 你可以找到图像是 SVG 或 PNG 然后将它重定向到特定的 requestBuilder
  • 您正在使用正确的 URL 从服务器下载图像,您知道 URL
  • 没有.using()
【解决方案2】:

我添加了一个灵活的解码管道来解码图像或 SVG,也许可以提供帮助!基于glide SVG example

解码器

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)
        }
    }
}

转码器

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
}

解码资源

data class SvgOrImageDecodedResource(
val svg:SVG? = null,
val bitmap: Bitmap? = null)

滑翔模块

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
}

}

【讨论】:

  • Glide v4 的加载速度比使用 Glide v3 加载 SVG 的库要慢一些,但是使用 gradle 的 SVG 库会导致问题(Glide 不同的版本)。如果您不太关心 SVG 速度,Josue 的回答是实现同时加载 SVG 和 PNG 图片的又好又快的方法
  • 经过进一步的测试,有一个问题 - 一些 SVG 是模糊的。但是将此解决方案与stackoverflow.com/questions/46680109/… 合并后,我设法同时加载了 png 和 svg,并使它们不模糊
【解决方案3】:

替代方式:kotlin + Coil

此解决方案适用于 .svg 、 .png 、 .jpg

添加依赖:

//Coil (https://github.com/coil-kt/coil)
implementation("io.coil-kt:coil:1.2.0")
implementation("io.coil-kt:coil-svg:1.2.0")

将此函数添加到您的代码中:

fun ImageView.loadUrl(url: String) {

val imageLoader = ImageLoader.Builder(this.context)
    .componentRegistry { add(SvgDecoder(this@loadUrl.context)) }
    .build()

val request = ImageRequest.Builder(this.context)
    .crossfade(true)
    .crossfade(500)
    .placeholder(R.drawable.placeholder)
    .error(R.drawable.error)
    .data(url)
    .target(this)
    .build()

imageLoader.enqueue(request)
}

然后在你的activity或者fragment中调用这个方法:

  imageView.loadUrl(url)
  // url example : https://upload.wikimedia.org/wikipedia/commons/3/36/Red_jungle_fowl_white_background.png

【讨论】:

  • 如果我用 PNG 替换 URL 也可以吗?
  • @Mauker 是的,那会很好用。我使用 .png 和 .jpg 网址进行了测试。如果你愿意,你可以测试它并告诉我反馈。
  • 这是否也将 SVG 作为字符串?
  • @Sattar 是的。 fun ImageView.loadUrl(url: String)
  • @RuchaBhattJoshi 您是否添加了两个依赖项: implementation("io.coil-kt:coil:1.2.0") implementation("io.coil-kt:coil-svg:1.2.0" )
【解决方案4】:

GlideToVectorYou 对我不起作用,所以我使用 coil 和线圈-svg 扩展库

【讨论】:

  • 我从没想过我会赞成一个只提到图书馆但你节省了我的时间的答案:D
  • 虽然我们最终使用 svg 解码器滑行,但我很高兴我提供了帮助:D
【解决方案5】:

对于那些因为正在寻找在 Xamarin Android 中加载 SVG 的方法而到达此线程的其他人,接受的答案将不起作用,因为 Xamarin Glide 中似乎没有很多这些类/方法nuget 包。这对我有用:

public static void SetSvgFromBytes (this ImageView imageView, byte[] bytes, int width, int height) {
            // Load the SVG from the bytes.
            var stream = new MemoryStream (bytes);
            var svg = SVG.GetFromInputStream (stream);
            // Create a Bitmap to render our SVG to.
            var bitmap = Bitmap.CreateBitmap (width, height, Bitmap.Config.Argb8888);
            // Create a Canvas to use for rendering.
            var canvas = new Canvas (bitmap);
            canvas.DrawRGB (255, 255, 255);
            // Now render the SVG to the Canvas.
            svg.RenderToCanvas (canvas);
            // Finally, populate the imageview from the Bitmap.
            imageView.SetImageBitmap (bitmap);
        }

它需要AndroidSVG.Xamarin nuget 包。

【讨论】:

    【解决方案6】:

    对于 Glide 4+ 使用这个名为 GlideToVectorYou 的库,它在内部使用 Glide。

    fun ImageView.loadSvg(url: String?) {
        GlideToVectorYou
            .init()
            .with(this.context)
            .setPlaceHolder(R.drawable.loading, R.drawable.actual)
            .load(Uri.parse(url), this)
    }
    

    来源:How to load remote svg files with Picasso library

    【讨论】:

      【解决方案7】:

      我也遇到了同样的问题,我所做的解决了我的问题,您只需 2 做 2 件完美工作的事情 转到链接https://github.com/corouteam/GlideToVectorYou 1-只需将过去的 Maven 依赖项复制到项目构建中 所有项目{ 存储库{ ... maven { url 'https://jitpack.io' } } } 2-在应用程序构建中添加依赖项 像实现'com.github.corouteam:GlideToVectorYou:v2.0.0'

      感谢它将解决加载 svg 确保您加载的内容与我正在加载的内容相同

      Glide.with(holder.itemView.getContext()) .load(imageurl) .apply(新的请求选项() .placeholder(R.drawable.placeholder) .dontAnimate() .fitCenter()) .into(holder.image);

      【讨论】:

        【解决方案8】:

        如果有人仍然需要它,使用 Glide v4,您可以使用 Glide-SVG 库轻松地将 SVG 支持添加到 Glide。 你也只需要导入 Android SVG 库,你就可以使用 Glide 使用这个简单、标准的代码行渲染任何 SVG:

        GlideApp.with(this).load(url).into(imageView)
        

        其中 GlideApp 是您本地生成的 Glide 模块,如下所示:

        @GlideModule
        class GlideModule : AppGlideModule() {
            override fun isManifestParsingEnabled() = false
        
            override fun applyOptions(context: Context, builder: GlideBuilder) {
                super.applyOptions(context, builder)
                builder.setLogLevel(Log.DEBUG)
            }
        }
        

        【讨论】:

        • 如果我同时导入 glide-svg 和 android-svg 我会收到一个编译错误,提示 Duplicate class com.caverock.androidsvg found in modules jetified-androidsvg-1.4 有近 100 个重复的类。
        • 尝试使用这些行添加库: implementation "com.github.qoqa:glide-svg:2.0.4" api "com.caverock:androidsvg:1.4" 我在两个不同的项目中编写它们与很多其他图书馆,我从来没有遇到过麻烦。
        【解决方案9】:

        使用 Sharp 库代替 Glide 库

        implementation 'com.pixplicity.sharp:library:1.1.0'
        
        InputStream stream = response.body().byteStream();
                           Sharp.loadInputStream(stream).into(target);
                            stream.close();  
        

        一个例子可以在这里看到https://www.geeksforgeeks.org/how-to-load-svg-from-url-in-android-imageview/

        fun fetchSvg(context: Context, url: String, target: ImageView) {
            val httpClient = OkHttpClient.Builder()
                .cache(Cache(context.cacheDir, 5 * 1024 * 1014))
                .build()
         
            val request: Request = Request.Builder().url(url).build()
            httpClient.newCall(request).enqueue(object : Callback {
                override fun onFailure(call: Call?, e: IOException?) {
                    // we are adding a default image if we gets any error.
                    target.setImageResource(R.drawable.ic_app_logo)
                }
        
                @Throws(IOException::class)
                override fun onResponse(call: Call?, response: Response) {
               
                    response.body()?.apply {
                        val stream = this.byteStream()
                        Sharp.loadInputStream(stream).into(target)
                        stream.close()
                    }
                }
            })
        }
        

        使用代码

         if(item.logo.endsWith("svg"))
                       Media.fetchSvg(icon.context,item.logo, icon)
                    else{
                       Glide.with(icon.context).load(Uri.parse(item.logo)).into(icon)
                    }
        

        【讨论】:

          猜你喜欢
          • 2021-07-08
          • 2022-12-12
          • 2018-07-28
          • 1970-01-01
          • 1970-01-01
          • 2019-09-18
          • 2017-05-30
          • 2018-03-22
          • 2016-06-01
          相关资源
          最近更新 更多