Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Deslizamiento: cargar de forma desplegable pero no escalar el marcador de posición

¿Hay alguna manera de usar Glide para asignar un marcador de posición pero mantener esta imagen a su escala original? Tengo un ImageView con un tamaño variable (dependiendo de la imagen entrante) que establezco antes de llamar a Glide.with().load().into() y quiero usar un marcador de posición para él, pero no quiero que el PH sea Redimensionado al tamaño del ImageView , quiero que mantenga su tamaño original.

Hasta ahora no pude encontrar una manera de hacer esto.

3 Solutions collect form web for “Deslizamiento: cargar de forma desplegable pero no escalar el marcador de posición”

Re: Comentario de Gregs : Le di otra foto (con casi un año de XP extra) y surgió con esto:

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

Similar a mi otra solución y el siguiente wrapper de animación:

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

Las partes triviales de las implementaciones se omite, el constructor de cada clase inicializa los campos de los argumentos. Código completo disponible en GitHub en TWiStErRob / glide-support .

Marcador de posición de crossFaded


Si estás atascado en una versión anterior de Glide (antes de la versión 3.8.0), el mismo efecto puede lograrse mediante:

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

Observe cómo las dos soluciones requieren la misma cantidad de clases, pero la solución posterior a la 3.8.0 tiene una mejor separación de las preocupaciones y se puede almacenar en caché en una variable para evitar asignaciones.

Hay un problema conocido de Glide de marcadores de posición que distorsionan las imágenes cargadas y viceversa . Sin embargo creo que no se ven afectados por eso.

Parece que lo que quieres es mostrar el marcador de posición scaleType="center" con scaleType="center" y quieres que la imagen cargada sea scaleType="fitCenter" . Así es como lo expresas en Glide. Añadir android:scaleType="center" en el XML y utilizar la siguiente línea de carga Glide:

 Glide.with(...).load(...).placeholder(R.drawable....).fitCenter().into(imageView); 

El truco es que el marcador de posición se establece a través de setImageDrawable() por lo que el ImageView sólo se mostrará como de costumbre, pero le dices a Glide para utilizar el FitCenter explícitamente que se ajuste a la imagen cargada muy bien dentro de la ImageView de diseño a través de una transformación y, A través de setImageDrawable() . Dado que la imagen ajustada es un ajuste perfecto, el center sólo dibujará la imagen que cubra todo el área de la vista.

También puede usar .centerCrop() la misma manera.

Si algo está mal puedes intentar .asBitmap() y .dontAnimate() , que ayudan la mayoría del tiempo de una manera u otra.

Lo hago como se menciona a continuación:

La idea es configurar el tipo de escala a como lo requiera el titular del lugar inicialmente y adjuntar el oyente para cambiar el tipo de escala de nuevo a según lo requiera la imagen descargada después de descargar la imagen.

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

Mi transición dibujable (R.drawable.anim_image_placeholder):

(No es necesario si se utiliza una imagen estática)

 <?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> 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.