[英]Progress bar while loading image using Glide
Can I load a spinner in placeholder with rotating animation until the image is loaded using Glide?在使用 Glide 加载图像之前,我可以在占位符中加载带有旋转动画的微调器吗?
I am trying to do that using .placeholder(R.Drawable.spinner) no animation is coming up?我正在尝试使用 .placeholder(R.Drawable.spinner) 来做到这一点,没有动画出现?
It would be great if somebody could help me out?如果有人可以帮助我,那就太好了?
Thanks!谢谢!
Edit: This is super simple now with the CircularProgressDrawable编辑:现在使用CircularProgressDrawable这非常简单
build.gradle构建.gradle
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
MyGlideModule.kt MyGlideModule.kt
@GlideModule
class MyGlideModule : AppGlideModule()
MainActivity.kt主活动.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)
}
These are some other Glide snippets这些是其他一些Glide 片段
Old answer: You could also create a normal ProgressBar, and then hide it on Glide's onResourceReady()
.旧答案:您也可以创建一个普通的 ProgressBar,然后将其隐藏在 Glide 的
onResourceReady()
。
The method that will be called when the resource load has finished.
资源加载完成后将调用的方法。
Example :示例:
MainActivity.java主活动.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 (layout): 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_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>
Result:结果:
You can set progress value whatever you want with my GlideImageLoader.您可以使用我的 GlideImageLoader 随意设置进度值。
I hope it will solve your question.我希望它能解决你的问题。
I encapsulate Image loader with progress in GlideImageLoader.java & ProgressAppGlideModule .java我在 GlideImageLoader.java 和 ProgressAppGlideModule .java 中封装了带有进度的图像加载器
How to implement with 3 steps:如何通过3个步骤实现:
1. build.gradle 1.构建.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 into Your Project 2. 将 GlideImageLoader.java 和 ProgressAppGlideModule.Java 克隆到您的项目中
3. Simple Use anywhere 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);
Complete Java code for clone:克隆的完整Java代码:
GlideImageLoader.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 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;
}
};
}
}
}
I was writing an app in Kotlin and was having this exact problem, but, unfortunately, the accepted answer was in Java.我正在用 Kotlin 编写一个应用程序并且遇到了这个确切的问题,但不幸的是,接受的答案是用 Java 编写的。 So, I rewrote it in Kotlin.
所以,我用 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)
Yes we can show loader on ImageView using Glide RequestOptions.是的,我们可以使用 Glide RequestOptions 在 ImageView 上显示加载器。
1)Use below compile line in app level gradle file. 1) 在应用程序级别的 gradle 文件中使用以下编译行。
implementation 'com.github.bumptech.glide:glide:4.8.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
2)Add progress_animation.xml file in drawable 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)Add below loader_test.png image in drawable 3)在drawable中添加loader_test.png图片
4)Create RequestOption as below 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)Finally use this to load image as below 5)最后使用它来加载图像如下
Glide.with(this).load(//*Your image url*//).apply(options).into(image_view);
Here is my complete solution with a circle loading progress.这是我的完整解决方案,带有圆形加载进度。 I think it is better to use
requestOptions
attributes to achieve this.我认为最好使用
requestOptions
属性来实现这一点。
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.
And you got it.你明白了。
Another trick: Put your ImageView
inside a RelativeLayout
with a ProgressBar
behind it.另一个技巧:把你的
ImageView
放在一个RelativeLayout
里面,后面有一个ProgressBar
。 Then load the image via Glide or Picasso.然后通过 Glide 或 Picasso 加载图像。 It will do the job for you without any deep digging.
无需任何深入挖掘,它就会为您完成工作。 You don't need to hide or show the progressbar anymore.
您不再需要隐藏或显示进度条。 It will be fully overlapped by the image.
它将与图像完全重叠。
<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>
Try using RequestOptions尝试使用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);
This is the one way you can implement loading image using with Glide .这是您可以使用Glide实现加载图像的一种方法。
Step -1 create drawable as 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%"/>
step 2 download loader_test and save in drawable.
step 3 for animate loading
step 4 in case of error user can set error image in error
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.