使用 Glide 加载图像时的进度条

Posted

技术标签:

【中文标题】使用 Glide 加载图像时的进度条【英文标题】:Progress bar while loading image using Glide 【发布时间】:2016-05-20 06:06:10 【问题描述】:

在使用 Glide 加载图像之前,我可以在占位符中加载带有旋转动画的微调器吗?

我正在尝试使用 .placeholder(R.Drawable.spinner) 来做到这一点,没有动画出现?

如果有人能帮帮我就好了?

谢谢!

【问题讨论】:

***.com/questions/39263403/… 请解决这个问题 【参考方案1】:

编辑:现在使用CircularProgressDrawable 非常简单

build.gradle

implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"

MyGlideModule.kt

@GlideModule
class MyGlideModule : AppGlideModule()

MainActivity.kt

override fun onCreate(savedInstanceState: Bundle?) 
  super.onCreate(savedInstanceState)
  setContentView(R.layout.activity_main)

  val circularProgressDrawable = CircularProgressDrawable(this)
  circularProgressDrawable.strokeWidth = 5f
  circularProgressDrawable.centerRadius = 30f
  circularProgressDrawable.start()

  GlideApp.with(applicationContext)
      .load("https://raw.githubusercontent.com/bumptech/glide/master/static/glide_logo.png")
      .placeholder(circularProgressDrawable)
      .into(a_main_image)

这些是其他一些Glide snippets


老答案:你也可以创建一个普通的ProgressBar,然后隐藏在Glide的onResourceReady()上。

资源加载完成时将调用的方法。


例子

MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final ImageView imageView = (ImageView) findViewById(R.id.img_glide);
    final ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress);

    Glide.with(this)
            .load("https://raw.githubusercontent.com/bumptech/glide/master/static/glide_logo.png")
            .listener(new RequestListener<Drawable>() 
                @Override
                public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) 
                    progressBar.setVisibility(View.GONE);
                    return false;
                

                @Override
                public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) 
                    progressBar.setVisibility(View.GONE);
                    return false;
                
            )
            .into(imageView);

activity_main.xml(布局):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    tools:context=".MainActivity">

    <ProgressBar
        android:id="@+id/progress"
        android:layout_
        android:layout_
        android:visibility="visible" />

    <ImageView
        android:id="@+id/img_glide"
        android:layout_
        android:layout_ />

</RelativeLayout>

结果:

【讨论】:

onException 应该做 progressBar.setVisibility(View.GONE);也。 :) 这很好,但没有显示出进步的价值。如何添加? 虽然我已经导入了 Glide 库,但无法解析 GlideDrawable 类。我是否必须添加任何其他库才能使用 GlideDrawable? 您可能正在导入 Glide 的 RC1 版本,他们将 GlideDrawable 替换为 Drawable。现在尝试导入compile 'com.github.bumptech.glide:glide:3.8.0 CircularProgressDrawable 目前已弃用。如果您想完全控制正在加载的图像,我建议您使用 Mark Cheng 的回答。 developer.android.com/reference/android/support/v4/widget/…【参考方案2】:

您可以使用我的 GlideImageLoader 任意设置进度值。

我希望它能解决你的问题。

我在 GlideImageLoader.java 和 ProgressAppGlideModule .java 中封装了带有进度的图像加载器

如何分三步实施:

1. build.gradle

//Glide
implementation 'com.github.bumptech.glide:glide:4.4.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.4.0'
implementation 'com.github.bumptech.glide:okhttp3-integration:4.4.0'

2.将 GlideImageLoader.java 和 ProgressAppGlideModule.Java 克隆到您的项目中

3.简单随处使用

RequestOptions options = new RequestOptions()
                    .centerCrop()
                    .placeholder(R.drawable.placeholder)
                    .error(R.drawable.ic_pic_error)
                    .priority(Priority.HIGH);

new GlideImageLoader(YOUR.imageView,  
                     YOUR.progressBar).load(url,options);

用于克隆的完整 Java 代码:

GlideImageLoader.java

public class GlideImageLoader 

    private ImageView mImageView;
    private ProgressBar mProgressBar;

    public GlideImageLoader(ImageView imageView, ProgressBar progressBar) 
        mImageView = imageView;
        mProgressBar = progressBar;
    

    public void load(final String url, RequestOptions options) 
        if (url == null || options == null) return;

        onConnecting();

        //set Listener & start
        ProgressAppGlideModule.expect(url, new ProgressAppGlideModule.UIonProgressListener() 
            @Override
            public void onProgress(long bytesRead, long expectedLength) 
                if (mProgressBar != null) 
                    mProgressBar.setProgress((int) (100 * bytesRead / expectedLength));
                
            

            @Override
            public float getGranualityPercentage() 
                return 1.0f;
            
        );
        //Get Image
        Glide.with(mImageView.getContext())
                .load(url)
                .transition(withCrossFade())
                .apply(options.skipMemoryCache(true))
                .listener(new RequestListener<Drawable>() 
                    @Override
                    public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) 
                        ProgressAppGlideModule.forget(url);
                        onFinished();
                        return false;
                    

                    @Override
                    public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) 
                        ProgressAppGlideModule.forget(url);
                        onFinished();
                        return false;
                    
                )
                .into(mImageView);
    


    private void onConnecting() 
        if (mProgressBar != null) mProgressBar.setVisibility(View.VISIBLE);
    

    private void onFinished() 
        if (mProgressBar != null && mImageView != null) 
            mProgressBar.setVisibility(View.GONE);
            mImageView.setVisibility(View.VISIBLE);
        
    

ProgressAppGlideModule.java

@GlideModule
public class ProgressAppGlideModule extends AppGlideModule 

    @Override
    public void registerComponents(Context context, Glide glide, Registry registry) 
        super.registerComponents(context, glide, registry);
        OkHttpClient client = new OkHttpClient.Builder()
                .addNetworkInterceptor(new Interceptor() 
                    @Override
                    public Response intercept(Chain chain) throws IOException 
                        Request request = chain.request();
                        Response response = chain.proceed(request);
                        ResponseProgressListener listener = new DispatchingProgressListener();
                        return response.newBuilder()
                                .body(new OkHttpProgressResponseBody(request.url(), response.body(), listener))
                                .build();
                    
                )
                .build();
        registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(client));
    

    public static void forget(String url) 
        ProgressAppGlideModule.DispatchingProgressListener.forget(url);
    
    public static void expect(String url, ProgressAppGlideModule.UIonProgressListener listener) 
        ProgressAppGlideModule.DispatchingProgressListener.expect(url, listener);
    

    private interface ResponseProgressListener 
        void update(HttpUrl url, long bytesRead, long contentLength);
    

    public interface UIonProgressListener 
        void onProgress(long bytesRead, long expectedLength);
        /**
         * Control how often the listener needs an update. 0% and 100% will always be dispatched.
         * @return in percentage (0.2 = call @link #onProgress around every 0.2 percent of progress)
         */
        float getGranualityPercentage();
    

    private static class DispatchingProgressListener implements ProgressAppGlideModule.ResponseProgressListener 
        private static final Map<String, UIonProgressListener> LISTENERS = new HashMap<>();
        private static final Map<String, Long> PROGRESSES = new HashMap<>();

        private final Handler handler;

        DispatchingProgressListener() 
            this.handler = new Handler(Looper.getMainLooper());
        

        static void forget(String url) 
            LISTENERS.remove(url);
            PROGRESSES.remove(url);
        

        static void expect(String url, UIonProgressListener listener) 
            LISTENERS.put(url, listener);
        

        @Override
        public void update(HttpUrl url, final long bytesRead, final long contentLength) 
            //System.out.printf("%s: %d/%d = %.2f%%%n", url, bytesRead, contentLength, (100f * bytesRead) / contentLength);
            String key = url.toString();
            final UIonProgressListener listener = LISTENERS.get(key);
            if (listener == null) 
                return;
            
            if (contentLength <= bytesRead) 
                forget(key);
            
            if (needsDispatch(key, bytesRead, contentLength, listener.getGranualityPercentage())) 
                handler.post(new Runnable() 
                    @Override
                    public void run() 
                        listener.onProgress(bytesRead, contentLength);
                    
                );
            
        

        private boolean needsDispatch(String key, long current, long total, float granularity) 
            if (granularity == 0 || current == 0 || total == current) 
                return true;
            
            float percent = 100f * current / total;
            long currentProgress = (long) (percent / granularity);
            Long lastProgress = PROGRESSES.get(key);
            if (lastProgress == null || currentProgress != lastProgress) 
                PROGRESSES.put(key, currentProgress);
                return true;
             else 
                return false;
            
        
    

    private static class OkHttpProgressResponseBody extends ResponseBody 
        private final HttpUrl url;
        private final ResponseBody responseBody;
        private final ResponseProgressListener progressListener;
        private BufferedSource bufferedSource;

        OkHttpProgressResponseBody(HttpUrl url, ResponseBody responseBody,
                                   ResponseProgressListener progressListener) 
            this.url = url;
            this.responseBody = responseBody;
            this.progressListener = progressListener;
        

        @Override
        public MediaType contentType() 
            return responseBody.contentType();
        

        @Override
        public long contentLength() 
            return responseBody.contentLength();
        

        @Override
        public BufferedSource source() 
            if (bufferedSource == null) 
                bufferedSource = Okio.buffer(source(responseBody.source()));
            
            return bufferedSource;
        

        private Source source(Source source) 
            return new ForwardingSource(source) 
                long totalBytesRead = 0L;

                @Override
                public long read(Buffer sink, long byteCount) throws IOException 
                    long bytesRead = super.read(sink, byteCount);
                    long fullLength = responseBody.contentLength();
                    if (bytesRead == -1)  // this source is exhausted
                        totalBytesRead = fullLength;
                     else 
                        totalBytesRead += bytesRead;
                    
                    progressListener.update(url, totalBytesRead, fullLength);
                    return bytesRead;
                
            ;
        
    

【讨论】:

你说得对,我本来想离开 cmets 而不是发布答案。但似乎我没有足够的声誉离开 cmets。我在此处添加必要的代码以防止链接无效。 使用进度条时不显示进度百分比,只显示加载条就可以了 终于成功了,我不得不用自定义进度和背景对进度条进行更改,谢谢 @Quicklearner 你能告诉我如何改变进度条的样式吗?所以它看起来像上面的演示图像? @DarariNurAmali 你想让代码在上面的图片中实现相同的功能吗?【参考方案3】:

我正在用 Kotlin 编写一个应用程序并且遇到了这个确切的问题,但不幸的是,接受的答案是用 Java 编写的。所以,我用 Kotlin 重写了它。

Glide.with(context)
                .load("<Insert Your URL>")
                .listener(object : RequestListener<Drawable> 
                    override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean 
                        progressBar.visibility = View.GONE
                        return false
                    

                    override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean 
                        progressBar.visibility = View.GONE
                        return false
                    
                )
                .into(holder.imageView)

【讨论】:

【参考方案4】:

是的,我们可以使用 Glide RequestOptions 在 ImageView 上显示加载器。 1) 在应用级 gradle 文件中使用下面的编译行。

implementation 'com.github.bumptech.glide:glide:4.8.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'

2)在drawable中添加progress_animation.xml文件

<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/loader_test"
    android:pivotX="50%"
    android:pivotY="50%"/>

3)在drawable中添加loader_test.png图片下方

4)如下创建RequestOption

public  RequestOptions options = new RequestOptions()
            .centerCrop()
            .placeholder(R.drawable.progress_animation)
            .error(R.drawable.user_image)
            .diskCacheStrategy(DiskCacheStrategy.ALL)
            .priority(Priority.HIGH)
            .dontAnimate()
            .dontTransform();

5)最后用这个来加载图片如下

Glide.with(this).load(//*Your image url*//).apply(options).into(image_view);

【讨论】:

实际上并不是动画。【参考方案5】:

这是我的完整解决方案,带有圆形加载进度。我认为最好使用requestOptionsattributes 来实现这一点。

CircularProgressDrawable circularProgressDrawable = new CircularProgressDrawable(context);
circularProgressDrawable.setStrokeWidth(5f);
circularProgressDrawable.setCenterRadius(30f);
circularProgressDrawable.start();

RequestOptions requestOptions = new RequestOptions();
requestOptions.placeholder(circularProgressDrawable);
requestOptions.error(R.drawable.ic_image_not_found);
requestOptions.skipMemoryCache(true);
requestOptions.fitCenter();


glide.load(imagePath) //passing your url to load image.
        .load(imagePath)
        .apply(requestOptions) // here you have all options you need
        .transition(DrawableTransitionOptions.withCrossFade()) // when image (url) will be loaded by glide then this face in animation help to replace url image in the place of placeHolder (default) image.
        .listener(requestListener)
        .into(view); //pass imageView reference to appear the image.

你明白了。

【讨论】:

什么是requestListener 它是可选的。你可以在这里查看文档:bumptech.github.io/glide/javadocs/4100/index.html?com/bumptech/…【参考方案6】:

另一个技巧:将您的ImageView 放入RelativeLayout 中,并在其后面加上ProgressBar。然后通过 Glide 或 Picasso 加载图像。它会为您完成这项工作,而无需任何深入挖掘。您不再需要隐藏或显示进度条。它将被图像完全重叠。

<RelativeLayout
            android:layout_
            android:layout_>
            <ProgressBar
                android:layout_centerInParent="true"
                android:layout_
                android:layout_/>
            <ImageView
                android:id="@+id/iv_image"
                android:layout_
                android:layout_
                android:scaleType="centerCrop"/>
</RelativeLayout>

【讨论】:

【参考方案7】:

尝试使用RequestOptions

RequestOptions requestOptions = new RequestOptions();
requestOptions.placeholder(R.drawable.ic_placeholder);
requestOptions.error(R.drawable.ic_error);


Glide.with(MainActivity.this)
            .load(url)
            .apply(requestOptions)
            .into(imageview);

这是您可以使用 Glide 实现加载图像的一种方法。

【讨论】:

但这不会像他想要的那样添加进度条,它只会加载图像【参考方案8】:

步骤-1创建drawable作为progress_animation.xml

<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/loader_test"
    android:pivotX="50%"
    android:pivotY="50%"/>

第2步下载loader_test并保存在drawable中。

动画加载的第 3 步

第4步出现错误用户可以在错误中设置错误图像

 Glide.with(this).load(url).apply(
         RequestOptions().placeholder(R.drawable.progress_animation).error((R.drawable.ic_account)).centerCrop()
                            .diskCacheStrategy(DiskCacheStrategy.ALL)
                            .priority(Priority.HIGH)
                            .transform(CenterCrop(), RoundedCorners(1000)))
                    .into(image_view)

【讨论】:

以上是关于使用 Glide 加载图像时的进度条的主要内容,如果未能解决你的问题,请参考以下文章

Glide4.10.0加载图片进度监听

c# 怎么实现页面提示加载中进度

像在 WhatsApp 中一样加载多个图像进度条

如何只实现一个圆形进度条,直到图像被滑动加载

如何在加载图像时添加进度条或循环进度此代码(颤振)?我尝试了不同的解决方案,但没有运气:(

一起学Android之ProgressBar