I use glide version 4.7.1
I wanna use default image when onLoadFailed.
this is my code
Glide.with(context).load(imageUrl).listener(new RequestListener<Drawable>() {
#Override
public boolean onLoadFailed(#Nullable GlideException e, Object model, com.bumptech.glide.request.target.Target<Drawable> target, boolean isFirstResource) {
// fail
// How can i use default image in imgvAssetPicture?
}
#Override
public boolean onResourceReady(Drawable resource, Object model, com.bumptech.glide.request.target.Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
// success
imgvLoadingProgressbar.setVisibility(View.INVISIBLE);
imgvAssetPicture.setVisibility(View.VISIBLE);
return false;
}
}).into(imgvAssetPicture);
Glide.with(passContext)
.applyDefaultRequestOptions(new RequestOptions()
.placeholder(R.drawable.ic_user_default)
.error(R.drawable.ic_user_default))
.load(url)
.into(image);
With version 4.7.1 (you are using), you can easily set these options.
placeHolder which shows when there is not image.
error when some URL fails to load.
Bonus
Are you using some ProgressBar with setting visibility, that's very old way to do.
See CircularProgressDrawable, which is very easy to use. Just pass this CircularProgressDrawable in your placeHolder.
Just Copy and Past these line of code wherever you want to use
Easy and simple
val circularProgressDrawable = CircularProgressDrawable(mContext)
circularProgressDrawable.strokeWidth = 5f
circularProgressDrawable.centerRadius = 30f
circularProgressDrawable.start()
Glide.with(mContext)
.load(specificCategoryObject.imgUrl)
.placeholder(R.drawable.circularProgressDrawable)
.transition(DrawableTransitionOptions.withCrossFade())
.error(R.drawable.img_place_holder)
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Drawable>?,
isFirstResource: Boolean
): Boolean {
circularProgressDrawable.alpha = 0
return false
}
override fun onResourceReady(
resource: Drawable?,
model: Any?,
target: Target<Drawable>?,
dataSource: DataSource?,
isFirstResource: Boolean,
): Boolean {
circularProgressDrawable.alpha = 0
return false
}
})
.into(holder.ivProductImage)
Related
I need to download an image and keep it as variable to put it into a notification:
.setLargeIcon(bitmap)
This is the code, I hope, it's clear by the comments what I try:
var bitmap = BitmapFactory.decodeResource(this#MainActivity.resources, R.drawable.notif_smiley) // create placeholder bitmap
val requestOptions = RequestOptions()
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
bitmap = Glide.with(this#MainActivity)
.asBitmap()
.load(imgurl)
.listener(object : RequestListener<Bitmap> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Drawable>?,
isFirstResource: Boolean
): Boolean {
// just dont do anything, keep the placeholder bitmap
return false
}
})
.apply(requestOptions)
.submit()
.get()
binding.contentMain.testingGlide.setImageBitmap(bitmap) // this is just for easy testing
I get all kind of error, I tried this based on an answer but there the bitmap goes directly into a view, please help :D
Inside your load failed method you're not setting any image so try changing that also try adding the onerror() method below code implementation should fix it
try{
lateinit var bitmap:Bitmap
bitmap = Glide.with(context)
.asBitmap()
.placeholder(R.mipmap.avengerswallp)
.load(imgUri)
.error(getnothumb())
.listener(object : RequestListener<Bitmap>{
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Bitmap>?, isFirstResource: Boolean): Boolean {
bitmap = myPlaceHolderBitmap
return true
}
override fun onResourceReady(resource: Bitmap?, model: Any?, target: Target<Bitmap>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
return false
}
}).submit().get()
}
catch(ex:Exception)
{
}
I'm using the following code:
Glide
.with(activity)
.load(hdImage)
.placeholder(R.drawable.loading)
.transition(DrawableTransitionOptions.withCrossFade(250))
.error(R.drawable.error)
.into(imageView);
HdImage is an URL string and could be invalid or empty, so I've set an error drawable.
But before showing it, i would like to try to load a second URL called, for example, sdImage.
Is there a way to achieve it?
Kishan put me on the right path to find the solution. To try a second image if the first fails:
Glide
.with(activity).load(hdImage)
.placeholder(R.drawable.loading)
.transition(DrawableTransitionOptions.withCrossFade(250))
.error(
Glide
.with(activity)
.load(sdImage)
.placeholder(R.drawable.loading)
.transition(DrawableTransitionOptions.withCrossFade(250))
.error(R.drawable.error)
)
.into(imageView);
You can try the below code. This is in Kotlin. In onLoadFailed, you can try for sdImage URL.
Glide.with(activity).load(hdImage)
.placeholder(R.drawable.loading)
.transition(DrawableTransitionOptions.withCrossFade(250))
.error(R.drawable.error)
.listener(object : RequestListener<Drawable> {
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
return false
}
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
return false
}
})
.into(imageView)
I have an Android widget for the home screen, whose layout is basically an ImageView:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/rl_ultraviolet_widget_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
android:gravity="center">
<ImageView
android:id="#+id/iv_ultraviolet_widget_image"
android:layout_width="#dimen/widget_size"
android:layout_height="#dimen/widget_size"
android:src="#drawable/ic_uvi_loading" />
</RelativeLayout>
The ImageView will be updated over the time with the "current" value, which is represented with an image (a drawable) using this code:
/**
* Updates ultraviolet index widget view.
*/
#JvmStatic
private fun updateWidgetViews(context: Context, appWidgetId: Int, #DrawableRes drawableId: Int) {
val widgetView = RemoteViews(context.packageName, R.layout.ultraviolet_widget)
// Set an Intent to launch MainActivity when clicking on the widget
val intent = Intent(context, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0)
widgetView.setOnClickPendingIntent(R.id.rl_ultraviolet_widget_layout, pendingIntent)
val appWidgetTarget = AppWidgetTarget(context, R.id.iv_ultraviolet_widget_image, widgetView, appWidgetId)
Glide
.with(context)
.asBitmap() // This is needed because AppWidgetTarget is a Bitmap target. See: https://github.com/bumptech/glide/issues/2717#issuecomment-351791721
.transition(BitmapTransitionOptions.withCrossFade())
.load(drawableId)
.into(appWidgetTarget)
pushWidgetUpdate(context, appWidgetId, widgetView)
}
/**
* Pushes update for a given widget.
*/
#JvmStatic
fun pushWidgetUpdate(context: Context, appWidgetId: Int, remoteViews: RemoteViews) {
val manager = AppWidgetManager.getInstance(context)
// Remember to check always for null in platform types (types ended in !).
// See: https://stackoverflow.com/a/43826700/5189200
manager?.let {
manager.updateAppWidget(appWidgetId, remoteViews)
Timber.d("Widget %d was updated", appWidgetId)
}
}
My question is how to also update the contentDescription property in the widget's ImageView with a description on every update and using Glide, so that my widget is more accessible and it can be used with TalkBack. I have searched, but I haven't found any example with Glide and a remote view.
Thanks in advance,
Xavi
You can add listener to Glide when load an image. So, when load image success, you update the contentDescription of imageView.
You can read how to add listener to Gilde in this: https://github.com/codepath/android_guides/wiki/Displaying-Images-with-the-Glide-Library#loading-errors
GlideApp.with(context)
.load("http://via.placeholder.com/300.png")
.placeholder(R.drawable.placeholder)
.error(R.drawable.imagenotfound)
.listener(new RequestListener<Drawable>() {
#Override
public boolean onLoadFailed(#Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
// log exception
Log.e("TAG", "Error loading image", e);
return false; // important to return false so the error placeholder can be placed
}
#Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
// load image success, update the contentDescription here
return false;
}
})
.into(ivImg);
Thanks to the help of #Nguyễn Quang Thọ, I found the solution. First, I created a data class (a tuple) in Kotlin for holding drawable and its associated string:
data class UltravioletImageContents(#DrawableRes val drawableId: Int, val contentDescription: String)
Second, I used the Glide result listener to add the contentDescription update and push the changes to the widget in my updateWidgetViews function.
#JvmStatic
private fun updateWidgetViews(context: Context, appWidgetId: Int, ultravioletImageContents: UltravioletImageContents) {
val widgetView = RemoteViews(context.packageName, R.layout.ultraviolet_widget)
// Set an Intent to launch MainActivity when clicking on the widget
val intent = Intent(context, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0)
widgetView.setOnClickPendingIntent(R.id.rl_ultraviolet_widget_layout, pendingIntent)
// Set image
val appWidgetTarget = AppWidgetTarget(context, R.id.iv_ultraviolet_widget_image, widgetView, appWidgetId)
Glide
.with(context)
.asBitmap() // This is needed because AppWidgetTarget is a Bitmap target. See: https://github.com/bumptech/glide/issues/2717#issuecomment-351791721
.transition(BitmapTransitionOptions.withCrossFade())
.load(ultravioletImageContents.drawableId)
.listener(object : RequestListener<Bitmap> {
override fun onLoadFailed(e: GlideException?, model: Any?, target: com.bumptech.glide.request.target.Target<Bitmap>?, isFirstResource: Boolean): Boolean {
Timber.e(e, "Drawable cannot be loaded and set in widget image view")
return false // Important to return false so the error placeholder can be placed
}
override fun onResourceReady(resource: Bitmap?, model: Any?, target: com.bumptech.glide.request.target.Target<Bitmap>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
// Set contentDescription in order to enable accessibility and be usable with TalkBack
widgetView.setContentDescription(R.id.iv_ultraviolet_widget_image, ultravioletImageContents.contentDescription)
pushWidgetUpdate(context, appWidgetId, widgetView)
return false
}
})
.into(appWidgetTarget)
}
Lastly, I would like to remark that pushWidgetUpdate was moved inside onResourceReady, since I think it doesn't have sense to update my widget without the image (but, maybe, I am missing something).
Here is a sample in Kotlin
Glide.with(context)
.load(data.imageUrl) // URL Of Image
.placeholder(R.drawable.placeholder)
.error(R.drawable.image_not_found)
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
return false // important to return false so the error placeholder can be placed
}
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
myImageView.contentDescription = data.accessibilityText
return false
}
})
.into(myImageView)
I am using Glide along with FirebaseStorage to fetch the photos stored in FirebaseStorage and show in the app. The problem is when photos were updated in the storage, The updated photos are not fetched, instead the old photos are being shown in the app. The device is online and its never updating the latest photos.
thirdPhotoStorageReference = FirebaseStorage.getInstance().reference.child("photos/${key}/3.jpg")
GlideApp.with(this)
.load(thirdPhotoStorageReference)
.override(screenWidth, screenHeight)
.listener(object : RequestListener<Drawable> {
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
showPhotoImageView(thirdPhotoImageView)
return false
}
override fun onLoadFailed(e: GlideException?, model: Any?, target: com.bumptech.glide.request.target.Target<Drawable>?, isFirstResource: Boolean): Boolean {
hidePhotoImageView(thirdPhotoImageView)
return false
}
})
.placeholder(circularProgressDrawable3)
.centerCrop()
.into(thirdPhotoImageView)
#GlideModule
class MyAppGlideModule : AppGlideModule() {
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
// Register FirebaseImageLoader to handle StorageReference
registry.append(StorageReference::class.java, InputStream::class.java,
FirebaseImageLoader.Factory())
}
}
Any help is appreciated.
Note: When I update the photo, It replaces the existing photo 3.jpg with latest.
Found an approach to solve the issue and posting it if someone has the same problem.
I was able to get the updated photos using the signature functionality of Glide. Please see the code below
thirdPhotoStorageReference.metadata.addOnSuccessListener {
GlideApp.with(this)
.load(thirdPhotoStorageReference)
.signature(ObjectKey(it.updatedTimeMillis))
.override(screenWidth, screenHeight)
.listener(object : RequestListener<Drawable> {
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
showPhotoImageView(thirdPhotoImageView)
return false
}
override fun onLoadFailed(e: GlideException?, model: Any?, target: com.bumptech.glide.request.target.Target<Drawable>?, isFirstResource: Boolean): Boolean {
hidePhotoImageView(thirdPhotoImageView)
return false
}
})
.placeholder(circularProgressDrawable3)
.centerCrop()
.into(thirdPhotoImageView)
}
The key here is the signature(ObjectKey(it.updatedTimeMillis)) which gets the update time of storage object and lets glide to refresh it.
Loading an image through data binding is easy. I am using Glide in my project. I have to set placeholder image which will change as per some selection by user. Can we use some expression which accepts imageurl and placeHolder image reference.
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/vehicle_1_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/margin_twenty"
app:layout_constraintEnd_toEndOf="#id/centerGuideline"
app:layout_constraintStart_toStartOf="#id/centerGuideline"
app:layout_constraintTop_toBottomOf="#id/txt_enter_vehicle_name"
app:loadImage="#{viewModel.imgUrl}" />
#BindingAdapter({"loadImage"})
public static void loadUrlImage(ImageView view, String url, int placeHolderImage){
ImageLoaderUtil.getInstance().loadImageWithCache(view, url, placeHolderImage);
}
public void loadImageWithCache(ImageView imageView, String url, int placeholderImage) {
Glide.with(imageView.getContext())
.load(url)
.apply(getDefaultGlideOptions())
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
.placeholder(placeholderImage)
.into(imageView);
}
Found this nice article: https://ayusch.com/databinding-with-glide-android/
We can also accept multiple arguments in our bindingadapter. For example, one may need to load an error image, or a placeholder while our image loads.
So I think listeners is the answer. Posting also the code in case the link is dead.
companion object {
#JvmStatic
#BindingAdapter(value = ["profileImage", "error"], requireAll = false)
fun loadImage(view: ImageView, profileImage: String, error: Int) {
Glide.with(view.context)
.load(profileImage)
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Drawable>?,
isFirstResource: Boolean
): Boolean {
view.setImageResource(error)
return true
}
override fun onResourceReady(
resource: Drawable?,
model: Any?,
target: Target<Drawable>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
view.setImageDrawable(resource)
return true
}
})
.into(view)
}
}
and in your layout:
app:error="#{user.errorImage}"
You can add multiple parameter in BindingAdapter just like this.
#BindingAdapter("url","placeHolderImage")
public static void loadUrlImage(ImageView view, String url, int placeHolderImage)
{
ImageLoaderUtil.getInstance().loadImageWithCache(view, url, placeHolderImage);
}
And you have to add field in Imageview xml just like this.
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/vehicle_1_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/margin_twenty"
app:layout_constraintEnd_toEndOf="#id/centerGuideline"
app:layout_constraintStart_toStartOf="#id/centerGuideline"
app:layout_constraintTop_toBottomOf="#id/txt_enter_vehicle_name"
app:url="#{viewModel.imgUrl}"
app:placeHolderImage="#{viewModel.}"
/>
You have pass two thing xml Url and Placeholder.