android - 使用 .asBitmap() 加载图像时,淡入淡出动画不起作用

标签 android android-animation android-imageview android-glide

我有这个代码

Glide
            .with(this)
            .load(mUrl)
            .asBitmap()
            .thumbnail(Glide
                    .with(this)
                    .load(mPreviewUrl)
                    .asBitmap()
                    .animate(R.anim.fade_in))
            .listener(new RequestListener<String, Bitmap>() {
                @Override
                public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {
                    mProgressBar.setVisibility(View.GONE);
                    return false;
                }

                @Override
                public boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {
                    mProgressBar.setVisibility(View.GONE);
                    return false;
                }
            })
            .into(new SimpleTarget<Bitmap>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
                @Override
                public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
                    mWallpaperImageView.setImageBitmap(resource);
                    createPaletteAsync(resource);
                }
            });

这会下载图像并返回一个 Bitmap 对象,然后我使用该对象通过 Palette 库生成调色板。我还想在 ImageView 中加载位图,我使用 mWallpaperImageView.setImageBitmap(resource) 来加载图像,没有任何淡入淡出或动画,以平滑加载.

如果我像这样使用 Glide :

Glide.with(this)
            .load(mUrl)
            .crossFade(500)
            .into(mImageView)

然后图像出现淡入淡出,但我没有 Bitmap 对象。

最佳答案

根据this answer ,

Unfortunately, there isn't a built in way to cross fade Bitmaps. You can however, use a custom BitmapImageViewTarget, and use a TransitionDrawable in onResourceReady() to cross fade.

幸运的是,有一个技巧可以启用 fading effect with bitmap in Glide

为此,您需要两个类(class),

FadingDrawable

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

GlideImageView

public class GlideImageView extends AppCompatImageView {
    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);
    }
}

现在将您的mWallpaperImageViewImageView更改为

<com.yourpackage.GlideImageView
    android:id="@+id/mWallpaperImageView" 
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

最后从 Glide 配置中删除所有外部动画效果,

Glide
     .with(this)
     .load(mUrl)
     .asBitmap()
     .thumbnail(Glide
                    .with(this)
                    .load(mPreviewUrl)
                    .asBitmap()
            .listener(new RequestListener<String, Bitmap>() {
                @Override
                public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {
                    mProgressBar.setVisibility(View.GONE);
                    return false;
                }

                @Override
                public boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {
                    mProgressBar.setVisibility(View.GONE);
                    return false;
                }
            })
            .into(new SimpleTarget<Bitmap>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
                @Override
                public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
                    mWallpaperImageView.setImageBitmap(resource);
                    createPaletteAsync(resource);
                }
            }); 

经过测试,工作正常!

关于android - 使用 .asBitmap() 加载图像时,淡入淡出动画不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43832510/

相关文章:

java - fragment 对话框动画正确但布局完全黑色

android - ViewPager 转换中的 PageCurl 动画?

java - 在两个图像之间循环

android - 如何计算ScrollView中ImageView的触摸位置,考虑缩放因素?

android - UDID 或 IMEI- 哪个更好?

android setError 方法干扰手动设置图标

java - 覆盖 android 硬件后退按钮功能

android - 使用 jackson 解析 Realm 模型

java - 属性动画的端监听器

java - 我可以使用什么代替 setImageResource() 来处理低于 16 的 API?