How can load the images with the Glide in ImageSwitcher - android

For creating image slide show , I want to use image switcher with timer .
I read this blog post it's very clear but it doesn't load images from network .
Now i want load images from network with Glide Library .
This is MainActivity :
public class MainActivity extends Activity {
private ImageSwitcher imageSwitcher;
private int[] gallery = { http://www.helloworld.com/image1.png, http://www.helloworld.com/image2.png, http://www.helloworld.com/image3.png,
http://www.helloworld.com/image4.png, };
private int position;
private static final Integer DURATION = 2500;
private Timer timer = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageSwitcher = (ImageSwitcher) findViewById(R.id.imageSwitcher);
imageSwitcher.setFactory(new ViewFactory() {
public View makeView() {
return new ImageView(MainActivity.this);
}
});
// Set animations
// https://danielme.com/2013/08/18/diseno-android-transiciones-entre-activities/
Animation fadeIn = AnimationUtils.loadAnimation(this, R.anim.fade_in);
Animation fadeOut = AnimationUtils.loadAnimation(this, R.anim.fade_out);
imageSwitcher.setInAnimation(fadeIn);
imageSwitcher.setOutAnimation(fadeOut);
}
// ////////////////////BUTTONS
/**
* starts or restarts the slider
*
* #param button
*/
public void start(View button) {
if (timer != null) {
timer.cancel();
}
position = 0;
startSlider();
}
public void stop(View button) {
if (timer != null) {
timer.cancel();
timer = null;
}
}
public void startSlider() {
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
// avoid exception:
// "Only the original thread that created a view hierarchy can touch its views"
runOnUiThread(new Runnable() {
public void run() {
imageSwitcher.setImageResource(gallery[position]);
position++;
if (position == gallery.length) {
position = 0;
}
}
});
}
}, 0, DURATION);
}
// Stops the slider when the Activity is going into the background
#Override
protected void onPause() {
super.onPause();
if (timer != null) {
timer.cancel();
}
}
#Override
protected void onResume() {
super.onResume();
if (timer != null) {
startSlider();
}
}
}
I try to load images with glide but i don't know what should i do .

It's pretty easy to do, all you need is to load image using Glide to the ImageView that you can get from ImageSwitcher by method imageSwitcher.getCurrentView(). So you need to replace code inside run of your runOnUiThread method to the next code:
Glide.with(MainActivity.this)
.load(gallery[position])
.asBitmap()
.listener(new RequestListener<String, Bitmap>() {
#Override
public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {
return false;
}
#Override
public boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {
position++;
if (position == gallery.length) {
position = 0;
}
imageSwitcher.setImageDrawable(new BitmapDrawable(getResources(), resource));
return true;
}
}).into((ImageView) imageSwitcher.getCurrentView());
Also don't forget to replace your image urls with appropriate urls (you now have there some dummy urls I see). So your gallery array should be a String[] array.
Don't forget also to include android.permission.INTERNET to your AndroidManifest.xml.
And finally you need to change android:layout_width property of your ImageSwitcher to match_parent in xml as Glide won't load image in it otherwise.

I think the approved answer is great but it is missing something key.
When they update the current image, this is basically just replacing the one in view. This means we might as well not use the ImageSwitcher at all. What we need to do, is update the next view and then show it. This will allow us to also see any transition effects we have added.
I have separated all this logic out within my own code to make it clean, but here it is in RAW form.
Setting up of your ImageSwitcher
Animation in = AnimationUtils.loadAnimation(this,android.R.anim.fade_in);
Animation out = AnimationUtils.loadAnimation(this,android.R.anim.fade_out);
imageSwitcher.setFactory(() -> {
ImageView imageView = new ImageView(getApplicationContext());
imageView.setLayoutParams(new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT
));
return imageView;
});
imageSwitcher.setInAnimation(in);
imageSwitcher.setOutAnimation(out);
Call this to then update the next image
RequestOptions requestOptions = new
RequestOptions().diskCacheStrategy(DiskCacheStrategy.ALL);
Bitmap nextImage = getAppropriateImage();
GlideApp.with(this)
.load(nextImage)
.apply(requestOptions)
.into((ImageView) imageSwitcher.getNextView());
imageSwitcher.showNext();

I used the version of #rom4ek but I had some crash:
Fatal Exception: java.lang.RuntimeException
Canvas: trying to use a recycled bitmap android.graphics.Bitmap#7ad49c4
I think that this is because the drawable is not set into the same ImageView passed to into(...).
I changed it to use the "next view". We have to set the visibility from GONE to INVISIBLE for Glide.
imageSwitcher.getNextView().setVisibility(View.INVISIBLE);
Glide.with(...)
.load(url)
.listener(new RequestListener<String, Bitmap>() {
#Override
public boolean onException(Exception e, String model, Target<Drawable> target, boolean isFirstResource) {
return false;
}
#Override
public boolean onResourceReady(Drawable resource, String model, Target<Drawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
imageSwitcher.setImageDrawable(resource);
return true;
}
}).into((ImageView) imageSwitcher.getNextView());
Kotlin version:
it.nextView.visibility = View.INVISIBLE
Glide.with(...)
.load(url)
.listener(object : RequestListener<Drawable> {
override fun onLoadFailed(
e: GlideException?,
model: Any?,
target: Target<Drawable>?,
isFirstResource: Boolean
): Boolean {
return false
}
override fun onResourceReady(
resource: Drawable?,
model: Any?,
target: Target<Drawable>?,
dataSource: DataSource?,
isFirstResource: Boolean
): Boolean {
it.setImageDrawable(resource)
return true
}
})
.into(it.nextView as ImageView)

Related

Play gifs sequentally in Android Studio

I'm trying to play two or more gifs in Android Studio. I'm using gif image view, but everytime I try to play more gifs in it, it displays only the last one. I can't find a way to play all of the gifs sequenatally. Any ideas please?
List gifs = Arrays.asList("gif1", "gif2", "gif3");
GifImageView gifView = view.findViewById(R.id.gifView);
for (int i=0; i < gifs.size(); i++) {
String word = gifs.get(i);
int idNum = getResources().getIdentifier(word, "drawable"
getActivity().getPackageName());
gifView.setImageResource(idNum);
}
Since you are using a loop to load gifs into the view, all gifs except the last one will be overwritten on each iteration, you should load the next gifs only after completely playing the gif.
Here is an example of achieving this using Glide and ImageView
public class MainActivity extends AppCompatActivity {
int gifLoaded = 0;
List gifs = Arrays.asList("https://i.kym-cdn.com/photos/images/newsfeed/001/708/675/4b5.gif",
"https://c.tenor.com/tOH34YVvpq4AAAAC/malayalam.gif",
"https://c.tenor.com/AKtcHf4ZTAsAAAAC/malayalam-kerala.gif"
);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadImage();
}
private void loadImage() {
if (gifLoaded > gifs.size() - 1) {
gifLoaded = 0;
}
String url = (String) gifs.get(gifLoaded);
ImageView giv = findViewById(R.id.iv_gif);
Glide.with(this).asGif().load(url).listener(new RequestListener<GifDrawable>() {
#Override
public boolean onLoadFailed(#Nullable GlideException e, Object model, Target<GifDrawable> target, boolean isFirstResource) {
return false;
}
#Override
public boolean onResourceReady(GifDrawable resource, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {
resource.setLoopCount(1);
resource.registerAnimationCallback(new Animatable2Compat.AnimationCallback() {
#Override
public void onAnimationEnd(Drawable drawable) {
gifLoaded++;
loadImage();
}
});
return false;
}
}).into(giv);
}
}

Picasso Target has been garbage collected

Good day.I have an google map with cluster manager.Simple one,where i use the cluster to draw markers grouped or not.Anyway i got an method callback from cluster manager which is the Cluster item render one.Inside that callback i am applying custom image to the marker:The user image inside marker.I found Picasso to be the best to handle bitmap loading and at the same time got me lots of headache.I am using Target class from Picasso to initiate the bitmap callbacks:OnPreLoad,OnFail,OnBitmapLoaded.The issue is that on first cluster item render the onBitmapLoaded not called and generally it is never gets called unless it has been touched second time.On first time nothing happens,no callback is triggered except OnPreLoad and by googling i found that the great Picasso holds weak reference to the class.I tried all the examples of the google:Making Target reference strong(getting the initialazation of class out of method and init the class inside my class like the follows)
#Override
protected void onClusterItemRendered(MarkerItem clusterItem, Marker marker) {
mMarker = marker;
mMarkerItem = clusterItem;
Picasso.with(mContext).load(clusterItem.getImageUrl()).transform(new CircleTransformation()).into(target);
}
private Target target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
Log.d(TAG, "onBitmapLoaded: ");
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
Log.d(TAG, "onBitmapFailed: ");
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
Log.d(TAG, "onPrepareLoad: ");
}
};
#Override
protected void onBeforeClusterItemRendered(MarkerItem item, MarkerOptions markerOptions) {
markerOptions.title(item.getTitle());
markerOptions.icon(item.getIcon());
}
At this point i get the same result....Sometimes the bitmap loaded and sometimes not.Mostly not...
Anyway i have tried to implement the interface class to my own class as follows:
public class PicassoMarkerView implements com.squareup.picasso.Target {
private static final String TAG = "MarkerRender";
private Bitmap mMarkerBitmap;
private ClusterManager<MarkerItem> mClusterManager;
private MarkerItem mMarkerItem;
private Marker mMarker;
public PicassoMarkerView() {
}
#Override
public int hashCode() {
return mMarker.hashCode();
}
#Override
public boolean equals(Object o) {
if (o instanceof PicassoMarkerView) {
Marker marker = ((PicassoMarkerView) o).mMarker;
return mMarker.equals(marker);
} else {
return false;
}
}
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap,
mMarkerBitmap.getWidth() - 15, (int) (mMarkerBitmap.getHeight() / 1.5 - 15),
false);
mMarker.setIcon(BitmapDescriptorFactory.fromBitmap(overlay(mMarkerBitmap, scaledBitmap, 8, 7)));
Log.d(TAG, "onBitmapLoaded: ");
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
Log.d(TAG, "onBitmapFailed: ");
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
Log.d(TAG, "onPrepareLoad: ");
}
private Bitmap overlay(Bitmap bitmap1, Bitmap bitmap2, int left, int top) {
Bitmap res = Bitmap.createBitmap(bitmap1.getWidth(), bitmap1.getHeight(),
bitmap1.getConfig());
Canvas canvas = new Canvas(res);
canvas.drawBitmap(bitmap1, new Matrix(), null);
canvas.drawBitmap(bitmap2, left, top, null);
return res;
}
public void setMarkerBitmap(Bitmap markerBitmap) {
this.mMarkerBitmap = markerBitmap;
}
public void setClusterManager(ClusterManager<MarkerItem> clusterManager) {
this.mClusterManager = clusterManager;
}
public void setMarkerItem(MarkerItem markerItem) {
this.mMarkerItem = markerItem;
}
public void setMarker(Marker marker) {
this.mMarker = marker;
}
}
Unfortunatally this is not working either...Same result...So please dear friends can you give me an working example of this?As far as i could google,the issue mostly happens to the user which try to do this inside loop and my onClusterItemRender some sort of loop lets say as it is triggered every time marker is visible to user,so yeah it is triggered several times and as fast as loop so give me some idea please and help me out...
Important to mention that i do not need to use methods from picasso like fetch(),get() as they are not necessary and not fitting the purpose of the app.
I encountered similar issue and holding reference to the target didn't help at all.
The purpose of my project was to use 2 different image downloading api's to show an images gallery and to give the user the ability to choose which api to use.
Beside Picasso I used Glide, and I was amazed by the results, Glide's api worked flawlessly in every aspect wile Picasso gave me hell (that was my first time using Glide, I usually used Picasso so far, seems like today it's gonna change ^^ ).
So my suggestion to you is:
Use glide over Picasso (no such weak reference on their target).
Since I had to use both libraries I ended up using get() in an handler, not sure if it will help you but it solved my problem:
handlerThread = new HandlerThread(HANDLER_THREAD_NAME);
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable() {
#Override
public void run() {
Bitmap bitmap = null;
try {
bitmap = picasso.with(appContext).load(url).get();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (bitmap != null) {
//do whatever you wanna do with the picture.
//for me it was using my own cache
imageCaching.cacheImage(imageId, bitmap);
}
}
}
});

Images are not stored in the cache

I have this method, everything is worked perfectly but images always got from server and not load from cache! what happened ?
public static void makeImageRequest(String Unique_ID, final View parentView, final int id) {
String url = FILE_UPLOAD_FOLDER + Unique_ID + ".png";
final int defaultImageResId = R.drawable.user;
// Retrieves an image specified by the URL, displays it in the UI.
ImageCacheManager.getInstance().getImage(url, new ImageListener() {
#Override
public void onErrorResponse(VolleyError error) {
ImageView imageView = (ImageView) parentView.findViewById(id);
imageView.setImageResource(defaultImageResId);
}
#Override
public void onResponse(ImageContainer response, boolean isImmediate) {
if (response.getBitmap() != null) {
ImageView imageView = (ImageView) parentView.findViewById(id);
imageView.setImageBitmap(response.getBitmap());
} else if (defaultImageResId != 0) {
ImageView imageView = (ImageView) parentView.findViewById(id);
imageView.setImageResource(defaultImageResId);
}
}
});
}
Just use Picasso instead ImageCacheManager. Picasso is a powerful image downloading and caching library for Android. Images add much-needed context and visual flair to Android applications. Picasso allows for hassle-free image loading in your application—often in one line of code!
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
Here also can manage whether the image is successfully downloaded or it fails:
Picasso.with(context)
.load("http://i.imgur.com/DvpvklR.png")
.into(imageView, new Callback() {
#Override
public void onSuccess() {
// your code
}
#Override
public void onError() {
// your code
}
});
You should only add this line in your gradle:
compile 'com.squareup.picasso:picasso:2.5.2'
Hope it helps!

Fade in animation while loading image Using Picasso

I want to show a fade effect when image is loading on Imageview. I am using picasso to cache image and display in image view. I have searched alot for this but couldnt find any solution.
I have used earlier before and i know in some version they had .fade(int Duration) method to fade image while loading but i couldnt find this method anymore.
Here is what i am doing now
Picasso.with(context)
.load(viewHolder.data.imageList.get(0).url)
.networkPolicy(NetworkPolicy.OFFLINE)
.placeholder(R.drawable.a_place_holder_list_view)
.error(R.drawable.a_place_holder_list_view)
.into(viewHolder.ivUser, context.loadImage(viewHolder.ivUser, viewHolder.data.imageList.get(0).url));
public Callback loadImage(RoundedImageView ivUser, String url) {
return new callback(ivUser, url);
}
public class callback implements Callback {
RoundedImageView imageView;
String url;
public callback(RoundedImageView imageView, String url) {
this.imageView = imageView;
this.url = url;
}
#Override
public void onSuccess() {
}
#Override
public void onError() {
Picasso.with(BaseActivity.this)
.load(url)
.placeholder(R.drawable.a_place_holder_list_view)
.error(R.drawable.a_place_holder_list_view)
.into(imageView, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
Log.v("Picasso", "Could not fetch image");
}
});
}
}
Please help me i have been stuck in this for quite long time.
Thanks in advance.
Quoting Jake Wharton's answer here:
If the image comes from anywhere except the memory cache the fade
should be automatically applied.
If you check the PicassoDrawable class
boolean fade = loadedFrom != MEMORY && !noFade;
if (fade) {
this.placeholder = placeholder;
animating = true;
startTimeMillis = SystemClock.uptimeMillis();
}
.
.
.
#Override public void draw(Canvas canvas) {
if (!animating) {
super.draw(canvas);
} else {
.
.
.
fade effect is already applied for images loaded from n/w and not memory/cache
and FADE_DURATION = 200f; //ms
To force fade, again quoting jake wharton's answer here:
You can specify noFade() and then always play an animation in the
image loaded callback. You can also rely on the callback being called
synchronously to determine if an animation needs played.
final AtomicBoolean playAnimation = new AtomicBoolean(true);
Picasso.with(context).load(..).into(imageView, new Callback() {
#Override public void onLoad() {
if (playAnimation.get()) {
//play fade
Animation fadeOut = new AlphaAnimation(0, 1);
fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setDuration(1000);
imageView.startAnimation(fadeOut);
Animation fadeOutPlaceholder = new AlphaAnimation(1, 0);
fadeOutPlaceholder.setInterpolator(new AccelerateInterpolator());
fadeOutPlaceholder.setDuration(1000);
placeHolderImageView.startAnimation(fadeOutPlaceholder);
}
}
//..
});
playAnimation.set(false);
You can simply do
Picasso.with(context).load(url).fetch(new Callback(){
#Override
public void onSuccess() {
imageView.setAlpha(0f);
Picasso.with(context).load(url).into(imageView);
imageView.animate().setDuration(300).alpha(1f).start();
}
#Override
public void onError() {
}
});
I do this:
Picasso.get().load(url).fit().noFade().centerInside().into(imageView, new Callback() {
#Override
public void onSuccess() {
imageView.setAlpha(0f);
imageView.animate().setDuration(200).alpha(1f).start();
}
#Override
public void onError(Exception e) {
}
});

Using Picasso library with ImageSwitcher is causing Object out of Memory errors

I want to load large bitmaps efficiently in my Image Switcher and i have been using Picasso for this purpose but now i am stuck at this point. Without Picasso a lot of OOMs and other nasty exceptions please tell me if I can use this library with Image Switcher too.
If yes then provide sample code.
Thanks!
imswitch.setFactory(new ViewFactory() {
#Override
public View makeView() {
ImageView imageView = new ImageView(getApplicationContext());
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.setLayoutParams(new ImageSwitcher.LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
return imageView;
}
} );
And onClick:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
currentIndex++;
// If index reaches maximum reset it
if(currentIndex==messageCount)
currentIndex=0;
ImageView imageView = (ImageView)findViewById(R.id.imswitch);
Picasso.with(getApplicationContext()).load(imageIds[currentIndex]).into(imageView);
Toast.makeText(getApplicationContext(), "Pressed "+currentIndex,Toast.LENGTH_LONG).show();
}
One of the possible way is to create own implementation using Target interface.
https://square.github.io/picasso/javadoc/com/squareup/picasso/Target.html
public class ImageSwitcherPicasso implements Target {
private ImageSwitcher mImageSwitcher;
private Context mContext;
public ImageSwitcherPicasso(Context context, ImageSwitcher imageSwitcher){
mImageSwitcher = imageSwitcher;
mContext = context;
}
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) {
mImageSwitcher.setImageDrawable(new BitmapDrawable(mContext.getResources(), bitmap));
}
#Override
public void onBitmapFailed(Drawable drawable) {
}
#Override
public void onPrepareLoad(Drawable drawable) {
}
}
Than just use as follow
ImageSwitcherPicasso mImageSwitcherPicasso = new ImageSwitcherPicasso(getActivity(), playerBackground);
Picasso.with(getActivity()).load(new File(path)).into(mImageSwitcherPicasso);
where playerBackground is reference to ImageSwitcher

Categories

Resources