Glide:加载drawable但不扩展占位符

Fer*_*ndo 19 android image drawable android-glide

有没有办法使用Glide分配占位符但是将此图像保持原始比例?我有一个ImageView可变大小(取决于传入的图像)我在调用之前设置Glide.with().load().into(),我想使用占位符,但不希望占位符调整大小ImageView,我希望它保持其原始尺寸.

到目前为止,我找不到办法做到这一点.

TWi*_*Rob 14

有一个已知的Glide问题是占位符扭曲了加载的图像,反之亦然.但是我认为你不受此影响.

这听起来像你想要的是显示占位符drawable与scaleType="center"你想要加载的图像scaleType="fitCenter".以下是您在Glide中表达的方式.添加android:scaleType="center"XML并使用以下Glide加载行:

Glide.with(...).load(...).placeholder(R.drawable....).fitCenter().into(imageView);
Run Code Online (Sandbox Code Playgroud)

诀窍是占位符是通过设置的,setImageDrawable()因此ImageView将像往常一样显示它,但是你告诉Glide使用FitCenter显式的,它将通过转换在ImageView的布局大小中很好地拟合加载的图像,然后通过它设置setImageDrawable().由于拟合图像非常合适,center因此只需绘制覆盖整个视图区域的图像.

您也可以使用.centerCrop()相同的方式.

如果事情是错的,你可以尝试.asBitmap().dontAnimate(),他们帮助大部分时间都在这样或那样的.


TWi*_*Rob 13

回复:Gregs评论:我给了它另一个镜头(用了将近一年的额外XP)并想出了这个:

<ImageView android:scaleType="center" ... />
Run Code Online (Sandbox Code Playgroud)

类似于我的其他解决方案和以下动画包装器:

...
    .fitCenter()
    .animate(new PaddingAnimationFactory<>(new DrawableCrossFadeFactory<GlideDrawable>(2000)))
    .into(imageView)
;

class PaddingAnimationFactory<T extends Drawable> implements GlideAnimationFactory<T> {
    private final DrawableCrossFadeFactory<T> realFactory;
    @Override public GlideAnimation<T> build(boolean isFromMemoryCache, boolean isFirstResource) {
        return new PaddingAnimation<>(realFactory.build(isFromMemoryCache, isFirstResource));
    }
}

class PaddingAnimation<T extends Drawable> implements GlideAnimation<T> {
    private final GlideAnimation<? super T> realAnimation;
    @Override public boolean animate(T current, final ViewAdapter adapter) {
        int width = current.getIntrinsicWidth();
        int height = current.getIntrinsicHeight();
        return realAnimation.animate(current, new PaddingViewAdapter(adapter, width, height));
    }
}

class PaddingViewAdapter implements ViewAdapter {
    @Override public Drawable getCurrentDrawable() {
        Drawable drawable = realAdapter.getCurrentDrawable();
        if (drawable != null) {
            int padX = Math.max(0, targetWidth - drawable.getIntrinsicWidth()) / 2;
            int padY = Math.max(0, targetHeight - drawable.getIntrinsicHeight()) / 2;
            if (padX != 0 || padY != 0) {
                drawable = new InsetDrawable(drawable, padX, padY, padX, padY);
            }
        }
        return drawable;
    }
    @Override public void setDrawable(Drawable drawable) {
        if (VERSION.SDK_INT >= VERSION_CODES.M && drawable instanceof TransitionDrawable) {
            // For some reason padding is taken into account differently on M than before in LayerDrawable
            // PaddingMode was introduced in 21 and gravity in 23, I think NO_GRAVITY default may play
            // a role in this, but didn't have time to dig deeper than this.
            ((TransitionDrawable)drawable).setPaddingMode(TransitionDrawable.PADDING_MODE_STACK);
        }
        realAdapter.setDrawable(drawable);
    }
}
Run Code Online (Sandbox Code Playgroud)

省略了实现的小部分,每个类的构造函数从参数初始化字段.在TWiStErRob/glide-support的GitHub上提供完整代码.

crossFaded占位符


如果您坚持使用较旧版本的Glide(3.8.0之前),可以通过以下方式实现相同的效果:

.fitCenter()
.placeholder(R.drawable.glide_placeholder)
.crossFade(2000)
.into(new GlideDrawableImageViewTarget(imageView) {
    @Override public void onResourceReady(GlideDrawable resource,
            GlideAnimation<? super GlideDrawable> animation) {
        super.onResourceReady(resource, new PaddingAnimation<>(animation));
    }
})
Run Code Online (Sandbox Code Playgroud)

请注意这两个解决方案如何需要相同数量的类,但3.8.0之后的解决方案可以更好地分离关注点,并且可以将其缓存在变量中以防止分配.