Bilah kemajuan saat memuat gambar menggunakan Glide


Jawaban:


231

Edit: Ini sangat sederhana sekarang dengan 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)
}

Ini adalah beberapa cuplikan Glide lainnya


Jawaban lama: Anda juga dapat membuat ProgressBar normal, lalu menyembunyikannya di Glide's onResourceReady().

Metode yang akan dipanggil ketika pemuatan sumber daya telah selesai.


Contoh :

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 (tata letak):

<?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>

Hasil:

masukkan deskripsi gambar di sini


6
OnException harus melakukan progressBar.setVisibility (View.GONE); terlalu. :)
AndroidRuntimeException

1
itu bagus tapi tidak menunjukkan nilai kemajuan. Bagaimana cara menambahkannya?
Han Whiteking

2
Kelas GlideDrawable tidak dapat diselesaikan meskipun saya telah mengimpor perpustakaan Glide. Apakah saya harus menambahkan pustaka tambahan untuk menggunakan GlideDrawable?
XerXes

Anda mungkin mengimpor Glide versi RC1 yang menggantikan GlideDrawable untuk Drawable. Coba impor compile 'com.github.bumptech.glide:glide:3.8.0sebagai gantinya untuk saat ini.
Evin1_

CircularProgressDrawable saat ini tidak digunakan lagi. Jika Anda ingin mengambil kendali penuh atas gambar yang sedang dimuat, saya sarankan jawaban Mark Cheng. developer.android.com/reference/android/support/v4/widget/…
Marcos Rocha

42

Anda dapat mengatur nilai kemajuan apa pun yang Anda inginkan dengan GlideImageLoader saya.

Saya harap ini akan menjawab pertanyaan Anda.

APLIKASI DEMO

Saya merangkum Image loader dengan kemajuan di GlideImageLoader.java & ProgressAppGlideModule .java

Cara menerapkan dengan 3 langkah:

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. Clone GlideImageLoader.java & ProgressAppGlideModule.Java ke dalam Proyek Anda

3. Penggunaan Sederhana di mana saja

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

Kode Java lengkap untuk klon:

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
Anda benar, saya awalnya ingin meninggalkan komentar daripada memposting jawaban. Tapi sepertinya saya tidak memiliki reputasi yang cukup untuk meninggalkan komentar. Saya menambahkan kode yang diperlukan di sini untuk mencegah tautan tidak valid.
Mark Cheng

persentase kemajuan tidak muncul saat menggunakan bilah kemajuan, hanya menunjukkan bilah memuat itu saja
Pelajar cepat

akhirnya berhasil, saya harus membuat perubahan untuk bilah kemajuan dengan kemajuan dan latar belakang khusus, Terima kasih
Pelajar cepat

@Quicklearner Bisakah Anda menunjukkan kepada saya cara mengubah gaya bilah kemajuan? jadi bisa terlihat seperti gambar demo di atas?
Darari Nur Amali

@DarariNurAmali Anda ingin menerapkan kode yang sama pada gambar di atas?
Pelajar cepat

12

Saya sedang menulis aplikasi di Kotlin dan mengalami masalah persis seperti ini, tetapi sayangnya, jawaban yang diterima ada di Java. Jadi, saya menulis ulang di 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)

5

Trik lainnya: Letakkan file ImageView bagian dalamRelativeLayout dengan a di ProgressBarbelakangnya. Kemudian muat gambar melalui Glide atau Picasso. Ini akan melakukan pekerjaan untuk Anda tanpa menggali lebih dalam. Anda tidak perlu menyembunyikan atau menampilkan bilah kemajuan lagi. Ini akan sepenuhnya tumpang tindih dengan gambar.

<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

Inilah solusi lengkap saya dengan kemajuan pemuatan lingkaran. Saya pikir lebih baik menggunakan requestOptionsatribut untuk mencapai ini.

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.

Dan Anda mendapatkannya.


3

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

Ini adalah salah satu cara Anda dapat mengimplementasikan pemuatan gambar menggunakan Glide .


2
tetapi ini tidak akan menambah bilah kemajuan seperti yang dia inginkan dalam pertanyaan itu hanya akan memuat gambar
Sattar

3

Ya, kami dapat menampilkan pemuat pada ImageView menggunakan Glide RequestOptions.
1) Gunakan di bawah garis kompilasi dalam file gradle tingkat aplikasi.

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

2) Tambahkan file progress_animation.xml di 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) Tambahkan di bawah gambar loader_test.png di drawable
masukkan deskripsi gambar di sini

4) Buat RequestOption seperti di bawah ini

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) Akhirnya gunakan ini untuk memuat gambar seperti di bawah ini

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

Ini sebenarnya tidak beranimasi.
Phani Rithvij
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.