Czy mogę załadować spinner do symbolu zastępczego z obracającą się animacją, dopóki obraz nie zostanie załadowany za pomocą Glide?
Próbuję to zrobić za pomocą .placeholder (R.Drawable.spinner), żadna animacja nie nadchodzi?
Byłoby wspaniale, gdyby ktoś mógł mi pomóc?
Dzięki!
android
android-glide
Sanjana Nair
źródło
źródło
Odpowiedzi:
Edycja: jest to teraz bardzo proste dzięki 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) }
Oto kilka innych fragmentów Glide
Stara odpowiedź: Możesz także utworzyć normalny pasek postępu, a następnie ukryć go w Glide's
onResourceReady()
.Przykład :
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 (układ):
<?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>
Wynik:
źródło
compile 'com.github.bumptech.glide:glide:3.8.0
.Możesz ustawić wartość postępu, co chcesz, za pomocą mojego GlideImageLoader.
Mam nadzieję, że to rozwiąże Twoje pytanie.
Hermetyzuję program ładujący obraz z postępem w GlideImageLoader.java i ProgressAppGlideModule .java
Jak wdrożyć w 3 krokach:
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. Sklonuj GlideImageLoader.java & ProgressAppGlideModule.Java do swojego projektu
3. Proste użycie w dowolnym miejscu
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);
Kompletny kod Java do klonu:
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; } }; } } }
źródło
Pisałem aplikację w Kotlinie i miałem dokładnie ten problem, ale niestety zaakceptowana odpowiedź była w Javie. Więc przepisałem to w Kotlinie.
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)
źródło
Kolejna sztuczka: umieść swoje
ImageView
wnętrzeRelativeLayout
aProgressBar
za nim. Następnie załaduj obraz przez Glide lub Picasso. Zrobi to za Ciebie bez głębokiego kopania. Nie musisz już ukrywać ani pokazywać paska postępu. Zostanie całkowicie zakryty przez obraz.<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>
źródło
Oto moje kompletne rozwiązanie z postępem ładowania koła. Myślę, że lepiej jest użyć
requestOptions
atrybutów, aby to osiągnąć.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.
I masz to.
źródło
Spróbuj użyć 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);
To jedyny sposób, w jaki możesz zaimplementować ładowanie obrazu za pomocą Glide .
źródło
Tak, możemy pokazać program ładujący w ImageView za pomocą Glide RequestOptions.
1) Użyj poniższej linii kompilacji w pliku gradle na poziomie aplikacji.
implementation 'com.github.bumptech.glide:glide:4.8.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
2) Dodaj plik progress_animation.xml do rysowania
<?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) Dodaj poniżej obraz loader_test.png do rysowania
4) Utwórz RequestOption jak poniżej
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) Na koniec użyj tego do załadowania obrazu, jak poniżej
Glide.with(this).load(//*Your image url*//).apply(options).into(image_view);
źródło