Closed start141 closed 9 years ago
You can use .animate(int) and give it an R.anim resource. the default animation is actually .crossFade() .
@MIkeeJY when use asBitmap()
, you can't use crossFade()
.
why not try animate(R.anim.xx)?
because I want to use the default animation
.
When you use asBitmap you tell Glide that you need a Bitmap object in your Target, which, as such, is just a bunch of pixels. crossFade works because the default loading transcodes to Drawable (instead of Bitmap) which can be replaced with a TransitionDrawable to do crossfade animation. Why do you need asBitmap?
You can try animating yourself by creating a custom target based on BitmapImageViewTarget (override setResource I think) or in a listener (start anim and return true).
Thanks for you reply!
Why do you need asBitmap?
Because in our App, we don't want to load GIF images(we want to load as static images). If I just want not to load gif, what should I do? And also with the default animation.
Yep, then you need asBitmap. Try the solutions I proposed, look around the sources of the classes I mentioned for guides.
Also keep in mind that .animate(R.anim.abc_fade_in)
is pretty close to crossfade.
I have tried use custom animation, but it's not good yet! I will try more times. Thanks!
You can't use the default animation because that requires a Drawable and you're loading a Bitmap. As @TWiStErRob suggested, you can use fade in. You can also use a RequestListener, convert your Bitmap into a Drawable and set a TransitionDrawable yourself. Doing so would be relatively straight forward.
I really like the way Picasso did for Animating Bitmap . I did the same and its seems very efficient and effective to me . I did tried TransitionDrawable and ObjectAnimator to Animate Alpha , but its not effective ,
you can try this
final public class FadingDrawable extends BitmapDrawable {
// Only accessed from main thread.
private static final float FADE_DURATION = 200; //ms
private final float density;
Drawable placeholder;
long startTimeMillis;
boolean animating;
int alpha = 0xFF;
FadingDrawable(Context context, Bitmap bitmap, Drawable placeholder) {
super(context.getResources(), bitmap);
this.density = context.getResources().getDisplayMetrics().density;
this.placeholder = placeholder;
animating = true;
startTimeMillis = SystemClock.uptimeMillis();
}
/**
* Create or update the drawable on the target {@link android.widget.ImageView} to display the supplied bitmap
* image.
*/
static public void setBitmap(ImageView target, Context context, Bitmap bitmap) {
if (bitmap != null && !bitmap.isRecycled()) {
Drawable placeholder = target.getDrawable();
if (placeholder instanceof AnimationDrawable) {
((AnimationDrawable) placeholder).stop();
}
FadingDrawable drawable = new FadingDrawable(context, bitmap, placeholder);
//this will avoid OverDraw
//target.setBackgroundDrawable(null);
//target.setBackgroundColor(0);
target.setImageDrawable(drawable);
}
}
/**
* Create or update the drawable on the target {@link android.widget.ImageView} to display the supplied
* placeholder image.
*/
static void setPlaceholder(ImageView target, Drawable placeholderDrawable) {
target.setImageDrawable(placeholderDrawable);
if (target.getDrawable() instanceof AnimationDrawable) {
((AnimationDrawable) target.getDrawable()).start();
}
}
@Override
public void draw(Canvas canvas) {
if (!animating) {
super.draw(canvas);
} else {
float normalized = (SystemClock.uptimeMillis() - startTimeMillis) / FADE_DURATION;
if (normalized >= 1f) {
animating = false;
placeholder = null;
super.draw(canvas);
} else {
if (placeholder != null) {
placeholder.draw(canvas);
}
int partialAlpha = (int) (alpha * normalized);
super.setAlpha(partialAlpha);
super.draw(canvas);
super.setAlpha(alpha);
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
invalidateSelf();
}
}
}
}
@Override
public void setAlpha(int alpha) {
this.alpha = alpha;
if (placeholder != null) {
placeholder.setAlpha(alpha);
}
super.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter cf) {
if (placeholder != null) {
placeholder.setColorFilter(cf);
}
super.setColorFilter(cf);
}
@Override
protected void onBoundsChange(Rect bounds) {
if (placeholder != null) {
placeholder.setBounds(bounds);
}
super.onBoundsChange(bounds);
}
}
public class GlideImageView extends ImageView {
public GlideImageView(Context context) {
this(context, null);
}
public GlideImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public GlideImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
Drawable placeholder = getDrawable();
if (placeholder instanceof AnimationDrawable) {
((AnimationDrawable) placeholder).stop();
Glide.clear(this);
}
}
@Override
public void setImageBitmap(Bitmap bitmap) {
if (bitmap != null) FadingDrawable.setBitmap(this, getContext(), bitmap);
}
public void setImageBitmapWithoutAnimation(Bitmap bitmap) {
super.setImageBitmap(bitmap);
}
}
Usage
Glide.with(mContext).load(url).asBitmap().error(R.drawable.ic_error_icon).into(viewHolder.getNetworkImageView());
Hope this could help you.
Thanks for your code! @vsahu1986. Your Animation looks like the Picasso, I think. I will try it.
yup code credit to @JakeWharton Picasso ,
I already mentioned Picasso did this way ...
@vsahu1986. awesome,man <3
@MIkeeJY man <3 ?
Hi @TWiStErRob
Could you please give this Picasso Bitmap Animation a try , as it does not increase memory usage .
This solution will always animate Image , whether it is from Memory Cache or Disk Cache
yup it will always fade your Bitmap , This is just a solution to animate bitmap , However it work well with RecyclerView , as you can use the cell to update the Image
https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html
instead of calling notifyDataSetChanged()
This is what you can try to control animation for in memory or remote image
public class GlideImageView extends ImageView {
public GlideImageView(Context context) {
this(context, null);
}
public GlideImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public GlideImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
Drawable placeholder = getDrawable();
if (placeholder instanceof AnimationDrawable) {
((AnimationDrawable) placeholder).stop();
Glide.clear(this);
}
}
@Override
public void setImageBitmap(Bitmap bitmap) {
if (bitmap != null) FadingDrawable.setBitmap(this, getContext(), bitmap);
}
public void setImageBitmapWithoutAnimation(Bitmap bitmap) {
super.setImageBitmap(bitmap);
}
public void loadUrl(String url) {
Glide.with(getContext()).load(url).asBitmap().error(R.drawable.ic_error_icon).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) {
if (isFromMemoryCache) {
setImageBitmapWithoutAnimation(resource);
} else {
setImageBitmap(resource);
}
return true;
}
}).into(this);
}
}
and
viewHolder.getNetworkImageView().loadUrl(url);
instead of
Glide.with(mContext).load(url).asBitmap().error(R.drawable.ic_error_icon).into(viewHolder.getNetworkImageView());
@ everyone this is close to what @sjudd was saying, except it uses everything built-in so you don't need to worry about not animating when memory cached or checking if there's a previous Drawable. Essentially 3-4 lines extra of code:
Glide
.with(context)
.load("https://media.giphy.com/media/4aBQ9oNjgEQ2k/giphy.gif")
.asBitmap()
.placeholder(android.R.drawable.gallery_thumb)
.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) {
ImageViewTarget imTarget = (ImageViewTarget)target;
return new DrawableCrossFadeFactory<Drawable>()
.build(isFromMemoryCache, isFirstResource)
.animate(new BitmapDrawable(imTarget.getView().getResources(), resource), imTarget);
}
})
.into(imageView)
;
If your .load()
accepts other than String just change the listener types to the correct class.
Check out #840 for a more modular code and potential future built-in feature.
Thanks TWiStErRob for your solution, it helped me to set a placeholder and an animation in a zoomable ViewPager with Bitmaps.
My Glide version is 3.6.1, load line is:
Sorry, I don't know how to add the
default animation
of Glide. I have tried useanimate()
, but I don't know how to build thedefault animation
! Sorry!