Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to add default animation when set asBitmap()? #605

Closed
start141 opened this issue Sep 1, 2015 · 21 comments
Closed

How to add default animation when set asBitmap()? #605

start141 opened this issue Sep 1, 2015 · 21 comments
Labels

Comments

@start141
Copy link
Contributor

start141 commented Sep 1, 2015

My Glide version is 3.6.1, load line is:

Glide.with(mActivity)
     .load(new File(item.getPath()))
     .asBitmap()
     .placeholder(R.drawable.default_picture)
     .centerCrop()
     .into(holder.image);

Sorry, I don't know how to add the default animation of Glide. I have tried use animate(), but I don't know how to build the default animation! Sorry!

@MIkeeJY
Copy link

MIkeeJY commented Sep 1, 2015

You can use .animate(int) and give it an R.anim resource. the default animation is actually .crossFade() .

@start141
Copy link
Contributor Author

start141 commented Sep 1, 2015

@MIkeeJY when use asBitmap(), you can't use crossFade().

@MIkeeJY
Copy link

MIkeeJY commented Sep 1, 2015

why not try animate(R.anim.xx)?

@start141
Copy link
Contributor Author

start141 commented Sep 1, 2015

because I want to use the default animation.

@TWiStErRob
Copy link
Collaborator

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).

@start141
Copy link
Contributor Author

start141 commented Sep 1, 2015

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.

@TWiStErRob
Copy link
Collaborator

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.

@start141
Copy link
Contributor Author

start141 commented Sep 1, 2015

I have tried use custom animation, but it's not good yet! I will try more times. Thanks!

@sjudd sjudd added the question label Sep 2, 2015
@sjudd
Copy link
Collaborator

sjudd commented Sep 2, 2015

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.

@vsahu1986
Copy link

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.

@start141
Copy link
Contributor Author

start141 commented Sep 9, 2015

Thanks for your code! @vsahu1986.
Your Animation looks like the Picasso, I think.
I will try it.

@vsahu1986
Copy link

yup code credit to @JakeWharton Picasso ,

I already mentioned Picasso did this way ...

@MIkeeJY
Copy link

MIkeeJY commented Sep 10, 2015

@vsahu1986. awesome,man <3

@start141
Copy link
Contributor Author

@MIkeeJY man <3 ?

@vsahu1986
Copy link

Hi @TWiStErRob

Could you please give this Picasso Bitmap Animation a try , as it does not increase memory usage .

@vipinhelloindia
Copy link

This solution will always animate Image , whether it is from Memory Cache or Disk Cache

@vsahu1986
Copy link

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()

@vsahu1986
Copy link

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());

@TWiStErRob
Copy link
Collaborator

@ 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.

@TWiStErRob
Copy link
Collaborator

Check out #840 for a more modular code and potential future built-in feature.

@harolhiguera
Copy link

Thanks TWiStErRob for your solution, it helped me to set a placeholder and an animation in a zoomable ViewPager with Bitmaps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants