Thanh tiến trình trong khi tải hình ảnh bằng cách sử dụng Glide


98

Tôi có thể tải một con quay trong trình giữ chỗ có hoạt ảnh xoay cho đến khi hình ảnh được tải bằng cách sử dụng Glide không?

Tôi đang cố gắng làm điều đó bằng cách sử dụng .placeholder (R.Drawable.spinner) không có hoạt ảnh nào xuất hiện?

Sẽ thật tuyệt nếu ai đó có thể giúp tôi?

Cảm ơn!


stackoverflow.com/questions/39263403/… Vui lòng giải quyết vấn đề đó
Đan Mạch Butt vào

Câu trả lời:


221

Chỉnh sửa: Điều này giờ đây cực kỳ đơn giản với 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)
}

Đây là một số đoạn Glide khác


Câu trả lời cũ: Bạn cũng có thể tạo một ProgressBar bình thường và sau đó ẩn nó trên onResourceReady () của Glide .

Phương thức sẽ được gọi khi quá trình tải tài nguyên kết thúc.


Ví dụ :

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 (bố cục):

<?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_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ProgressBar
        android:id="@+id/progress"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:visibility="visible" />

    <ImageView
        android:id="@+id/img_glide"
        android:layout_width="match_parent"
        android:layout_height="100dp" />

</RelativeLayout>

Kết quả:

nhập mô tả hình ảnh ở đây


6
OnException sẽ thực hiện tiến trình ProgressBar.setVisibility (View.GONE); quá. :)
AndroidRuntimeException

1
nó tốt nhưng nó không cho thấy giá trị của sự tiến bộ. Làm thế nào để thêm nó?
Han Whiteking

2
Không thể giải quyết lớp GlideDrawable mặc dù tôi đã nhập thư viện Glide. Tôi có phải thêm bất kỳ thư viện bổ sung nào để sử dụng GlideDrawable không?
XerXes

Có thể bạn đang nhập phiên bản RC1 của Glide, nơi họ đã thay thế GlideDrawable cho Drawable. Hãy thử nhập compile 'com.github.bumptech.glide:glide:3.8.0thay thế ngay bây giờ.
Evin1_

CircularProgressDrawable hiện không được dùng nữa. Nếu bạn muốn toàn quyền kiểm soát hình ảnh đang được tải, tôi đề xuất câu trả lời của Mark Cheng. developer.android.com/reference/android/support/v4/widget/…
Marcos Rocha

42

Bạn có thể đặt giá trị tiến độ bất cứ thứ gì bạn muốn với GlideImageLoader của tôi.

Tôi hy vọng nó sẽ giải quyết câu hỏi của bạn.

ỨNG DỤNG DEMO

Tôi đóng gói Trình tải hình ảnh với tiến trình trong GlideImageLoader.java & ProgressAppGlideModule .java

Cách thực hiện với 3 bước:

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. Nhân bản GlideImageLoader.java & ProgressAppGlideModule.Java vào dự án của bạn

3. Sử dụng đơn giản ở mọi nơi

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

Hoàn thành mã Java cho bản sao:

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

2
Bạn nói đúng, tôi ban đầu muốn để lại bình luận hơn là đăng câu trả lời. Nhưng có vẻ như tôi không có đủ danh tiếng để để lại bình luận. Tôi thêm mã cần thiết ở đây để ngăn chặn liên kết không hợp lệ.
Mark Cheng

tiến tỷ lệ không hiển thị trên thanh tiến trình sử dụng, chỉ hiển thị thanh tải thats it
Nhanh học

cuối cùng nó đã hoạt động, tôi phải thực hiện các thay đổi cho thanh tiến trình với tiến trình và nền tùy chỉnh, Cảm ơn
học nhanh

@Quicklearner bạn có thể chỉ cho tôi cách thay đổi kiểu thanh tiến trình không? vì vậy nó có thể trông giống như hình ảnh demo ở trên?
Darari Nur Amali,

@DarariNurAmali bạn muốn mã triển khai tương tự trong các hình ảnh trên?
học nhanh

11

Tôi đang viết một ứng dụng trong Kotlin và gặp phải vấn đề chính xác này, nhưng, thật không may, câu trả lời được chấp nhận là trong Java. Vì vậy, tôi đã viết lại nó trong 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

Một mẹo khác: Đặt ImageViewbên trong của bạn RelativeLayoutvới một ProgressBarphía sau nó. Sau đó tải hình ảnh qua Glide hoặc Picasso. Nó sẽ thực hiện công việc cho bạn mà không cần đào sâu. Bạn không cần phải ẩn hoặc hiển thị thanh tiến trình nữa. Nó sẽ được chồng lên hoàn toàn bởi hình ảnh.

<RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/_180sdp">
            <ProgressBar
                android:layout_centerInParent="true"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
            <ImageView
                android:id="@+id/iv_image"
                android:layout_width="match_parent"
                android:layout_height="@dimen/_180sdp"
                android:scaleType="centerCrop"/>
</RelativeLayout>

4

Đây là giải pháp hoàn chỉnh của tôi với tiến trình tải vòng kết nối. Tôi nghĩ tốt hơn là sử dụng requestOptionscác thuộc tính để đạt được điều này.

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.

Và bạn đã hiểu nó.


3

Hãy thử sử dụng 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);

Đây là một cách bạn có thể thực hiện tải hình ảnh bằng Glide .


2
nhưng điều này sẽ không thêm một thanh tiến trình như ông muốn trong câu hỏi nó chỉ sẽ tải hình ảnh
Sattar

3

Có, chúng tôi có thể hiển thị trình tải trên ImageView bằng cách sử dụng Glide RequestOptions.
1) Sử dụng dòng biên dịch bên dưới trong tệp gradle cấp ứng dụng.

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

2) Thêm tệp Progress_animation.xml trong drawable

<?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) Thêm hình ảnh loader_test.png bên dưới trong drawable
nhập mô tả hình ảnh ở đây

4) Tạo RequestOption như bên dưới

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) Cuối cùng sử dụng cái này để tải hình ảnh như bên dưới

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

Nó không thực sự hoạt hình.
Phani Rithvij 14/07/19
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.