Android 滑动:负载可牵引,但不';t刻度占位符

Android 滑动:负载可牵引,但不';t刻度占位符,android,image,drawable,android-glide,Android,Image,Drawable,Android Glide,有没有一种方法可以使用Glide指定占位符,但保持此图像的原始比例? 我有一个大小可变的ImageView(取决于传入的图像),我在调用Glide.with().load().into()之前设置了它,我想为它使用一个占位符,但不想将占位符调整为ImageView的大小,我希望它保持其原始大小 到目前为止,我找不到一个方法来做这件事。有一个问题。然而,我认为你没有受到影响 听起来您想要的是显示可使用scaleType=“center”绘制的占位符,并且希望加载的图像是scaleType=“fit

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

到目前为止,我找不到一个方法来做这件事。

有一个问题。然而,我认为你没有受到影响

听起来您想要的是显示可使用
scaleType=“center”
绘制的占位符,并且希望加载的图像是
scaleType=“fitCenter”
。下面是你在Glide中的表达方式。在XML中添加android:scaleType=“center”,并使用以下滑动加载行:

Glide.with(...).load(...).placeholder(R.drawable....).fitCenter().into(imageView);
诀窍在于占位符是通过
setImageDrawable()
设置的,因此ImageView将像往常一样显示它,但您告诉Glide显式使用
FitCenter
,它将通过变换使加载的图像与ImageView的布局大小很好地匹配,然后通过
setImageDrawable()
进行设置。由于拟合图像是完美的拟合,
center
将只绘制覆盖视图整个区域的图像

您也可以用同样的方法使用
.centerCrop()

如果出现问题,您可以尝试使用
.asBitmap()
.dontAnimate()
,它们在大多数情况下都会以某种方式提供帮助。

Re:: 我又给了它一次机会(用了将近一年的额外经验),并提出了以下建议:

<ImageView android:scaleType="center" ... />

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

...
    .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);
    }
}
。。。
.fitCenter()
.animate(新的PaddingAnimationFactory(新的DrawableCrossFadeFactory(2000)))
.into(图像视图)
;
类PaddingAnimationFactory实现GlideAnimationFactory{
私人最终可绘制交叉fadefactory重新工厂;
@重写公共动画生成(布尔值isFromMemoryCache,布尔值isFirstResource){
返回新的填充动画(realFactory.build(isFromMemoryCache,isFirstResource));
}
}
类填充动画实现了动画{

私人最终动画我像下面提到的那样做:

这样做的想法是,首先将缩放类型设置为占位符所需,然后在下载图像后,附加侦听器将缩放类型再次更改为下载图像所需的缩放类型

//ivBuilderLogo = Target ImageView
//Set the scale type to as required by your place holder
//ScaleType.CENTER_INSIDE will maintain aspect ration and fit the placeholder inside the image view
holder.ivBuilderLogo.setScaleType(ImageView.ScaleType.CENTER_INSIDE); 

//AnimationDrawable is required when you are using transition drawables
//You can directly send resource id to glide if your placeholder is static
//However if you are using GIFs, it is better to create a transition drawable in xml 
//& use it as shown in this example
AnimationDrawable animationDrawable;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
     animationDrawable=(AnimationDrawable)context.getDrawable(R.drawable.anim_image_placeholder);
else
     animationDrawable=(AnimationDrawable)context.getResources().getDrawable(R.drawable.anim_image_placeholder);
animationDrawable.start();

Glide.with(context).load(logo_url)
                   .placeholder(animationDrawable)
                   .listener(new RequestListener<String, GlideDrawable>() {
                        @Override
                        public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource)
                        {
                           return false;
                        }

                        //This is invoked when your image is downloaded and is ready 
                        //to be loaded to the image view
                        @Override
                        public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource)
                        {   
                        //This is used to remove the placeholder image from your ImageView 
                        //and load the downloaded image with desired scale-type(FIT_XY in this case)
                        //Changing the scale type from 'CENTER_INSIDE' to 'FIT_XY' 
                        //will stretch the placeholder for a (very) short duration,
                        //till the downloaded image is loaded
                        //setImageResource(0) removes the placeholder from the image-view 
                        //before setting the scale type to FIT_XY and ensures that the UX 
                        //is not spoiled, even for a (very) short duration
                            holder.ivBuilderLogo.setImageResource(0);
                            holder.ivBuilderLogo.setScaleType(ImageView.ScaleType.FIT_XY);
                            return false;
                        }
                    })
                    .into( holder.ivBuilderLogo);
//ivBuilderLogo=目标图像视图
//根据占位符的要求,将刻度类型设置为
//ScaleType.CENTER_INSIDE将保持纵横比,并将占位符放入图像视图中
holder.ivBuilderLogo.setScaleType(ImageView.ScaleType.CENTER_内);
//使用过渡绘图功能时,需要使用AnimationDrawable
//如果占位符是静态的,您可以直接向glide发送资源id
//但是,如果您使用的是GIF,那么最好创建一个可在xml中绘制的转换
//&如本例所示使用它
AnimationDrawable AnimationDrawable;
if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.LOLLIPOP)
animationDrawable=(animationDrawable)context.getDrawable(R.drawable.anim\u image\u占位符);
其他的
animationDrawable=(animationDrawable)context.getResources().getDrawable(R.drawable.anim\u image\u占位符);
animationDrawable.start();
Glide.with(context.load)(logo\u url)
.占位符(可动画绘制)
.listener(新的RequestListener(){
@凌驾
公共布尔onException(异常e、字符串模型、目标、布尔isFirstResource)
{
返回false;
}
//当您的图像已下载并准备就绪时,将调用此选项
//要加载到图像视图,请执行以下操作:
@凌驾
公共布尔值onResourceReady(GlideDrawable资源、字符串模型、目标、布尔值isFromMemoryCache、布尔值isFirstResource)
{   
//这用于从ImageView中删除占位符图像
//并加载所需比例类型的下载图像(在本例中为FIT_XY)
//将比例类型从“居中”更改为“适合”
//将在(非常)短的时间内拉伸占位符,
//直到下载的图像被加载
//setImageResource(0)从图像视图中删除占位符
//在将比例类型设置为适合_XY并确保UX
//即使在(非常)短的时间内,也不会被破坏
holder.ivBuilderLogo.setImageResource(0);
holder.ivBuilderLogo.setScaleType(ImageView.ScaleType.FIT_XY);
返回false;
}
})
.into(holder.ivBuilderLogo);
我的转换可绘制(R.drawable.anim\u image\u占位符):

(如果使用静态图像,则不需要)



此解决方案的问题:虽然它最初似乎有效,但请注意,在Glide将占位符淡入真实图像的过渡过程中,占位符图像会放大到fitCenter。这是一个大问题,因为我试图在此处保留淡入过渡。因此dontAnimate()违背了尝试这样做的目的。有什么想法吗?这个解决方案在android 5.x及以下版本上对我们有效。但在6和N上,填充动画的行为似乎没有达到预期,我们再次看到行为占位符在过渡到centerCrop视图的过程中增长。我们将进行研究,但如果其他人有看到6号的故障了吗
//ivBuilderLogo = Target ImageView
//Set the scale type to as required by your place holder
//ScaleType.CENTER_INSIDE will maintain aspect ration and fit the placeholder inside the image view
holder.ivBuilderLogo.setScaleType(ImageView.ScaleType.CENTER_INSIDE); 

//AnimationDrawable is required when you are using transition drawables
//You can directly send resource id to glide if your placeholder is static
//However if you are using GIFs, it is better to create a transition drawable in xml 
//& use it as shown in this example
AnimationDrawable animationDrawable;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
     animationDrawable=(AnimationDrawable)context.getDrawable(R.drawable.anim_image_placeholder);
else
     animationDrawable=(AnimationDrawable)context.getResources().getDrawable(R.drawable.anim_image_placeholder);
animationDrawable.start();

Glide.with(context).load(logo_url)
                   .placeholder(animationDrawable)
                   .listener(new RequestListener<String, GlideDrawable>() {
                        @Override
                        public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource)
                        {
                           return false;
                        }

                        //This is invoked when your image is downloaded and is ready 
                        //to be loaded to the image view
                        @Override
                        public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource)
                        {   
                        //This is used to remove the placeholder image from your ImageView 
                        //and load the downloaded image with desired scale-type(FIT_XY in this case)
                        //Changing the scale type from 'CENTER_INSIDE' to 'FIT_XY' 
                        //will stretch the placeholder for a (very) short duration,
                        //till the downloaded image is loaded
                        //setImageResource(0) removes the placeholder from the image-view 
                        //before setting the scale type to FIT_XY and ensures that the UX 
                        //is not spoiled, even for a (very) short duration
                            holder.ivBuilderLogo.setImageResource(0);
                            holder.ivBuilderLogo.setScaleType(ImageView.ScaleType.FIT_XY);
                            return false;
                        }
                    })
                    .into( holder.ivBuilderLogo);
<?xml version="1.0" encoding="utf-8"?>
<animation-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item android:drawable="@drawable/loading_frame1" android:duration="100" />
    <!--<item android:drawable="@drawable/loading_frame2" android:duration="100" />-->
    <item android:drawable="@drawable/loading_frame3" android:duration="100" />
    <!--<item android:drawable="@drawable/loading_frame4" android:duration="100" />-->
    <item android:drawable="@drawable/loading_frame5" android:duration="100" />
    <!--<item android:drawable="@drawable/loading_frame6" android:duration="100" />-->
    <item android:drawable="@drawable/loading_frame7" android:duration="100" />
    <!--<item android:drawable="@drawable/loading_frame8" android:duration="100" />-->
    <item android:drawable="@drawable/loading_frame9" android:duration="100" />
    <!--<item android:drawable="@drawable/loading_frame10" android:duration="100" />-->
</animation-list>