Redimensionnez l'image sur toute sa largeur et à hauteur variable avec Picasso

j'ai un listView avec un adaptateur qui contient ImageView de taille variable (largeur et hauteur). J'ai besoin de redimensionner les images chargent avec Picasso à la largeur maximale de la mise en page et une hauteur variable donnée par le rapport d'aspect de l'image.

j'ai vérifié cette question: redimensionner l'image sur toute sa largeur et à hauteur fixe avec Picasso

le fit() fonctionne, mais je n'ai rien trouvé pour garder le rapport d'aspect de image.

ce code fonctionne partiellement si j'ai fixé la hauteur dans la disposition de l'adaptateur:

Picasso.with(this.context).load(message_pic_url)
.placeholder(R.drawable.profile_wall_picture)
.fit().centerInside()
.into(holder.message_picture);

mais il génère des espaces vides entre les images du listView parce que les images peuvent ne pas avoir cette hauteur.

Merci d'avance.

72
demandé sur Community 2014-02-19 22:55:47

10 réponses

à partir de Picasso 2.4.0, cette opération est maintenant prise en charge directement . Il suffit d'ajouter une demande .resize() avec une des dimensions comme 0 . Par exemple, avoir une largeur variable, votre appel deviendrait:

Picasso.with(this.context)
       .load(message_pic_url)
       .placeholder(R.drawable.profile_wall_picture)
       .resize(0, holder.message_picture.getHeight()),
       .into(holder.message_picture);

notez que cet appel utilise .getHeight() et suppose donc que le message_picture a déjà été mesuré. Si ce n'est pas le cas, comme lorsque vous avez gonflé une nouvelle vue dans un ListAdapter , vous pouvez retarder cet appel jusqu'à après la mesure en ajoutant un OnGlobalLayoutListener à la vue:

holder.message_picture.getViewTreeObserver()
      .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            // Wait until layout to call Picasso
            @Override
            public void onGlobalLayout() {
                // Ensure we call this only once
                imageView.getViewTreeObserver()
                         .removeOnGlobalLayoutListener(this);


                Picasso.with(this.context)
                       .load(message_pic_url)
                       .placeholder(R.drawable.profile_wall_picture)
                       .resize(0, holder.message_picture.getHeight())
                       .into(holder.message_picture);
            }
        });
75
répondu thirtythreeforty 2016-08-01 14:34:37

je suis tombé sur la même question et il m'a fallu un certain temps pour trouver une solution, mais je suis finalement tombé sur quelque chose qui fonctionne pour moi.

D'abord J'ai changé L'appel de Picasso en

Picasso.with(this.context).load(message_pic_url)
.placeholder(R.drawable.profile_wall_picture)
.into(holder.message_picture);

supprimant le fit et le centerInside . Ensuite, vous devez ajouter les lignes suivantes À L'ImageView dans votre XML

android:scaleType="fitStart"
android:adjustViewBounds="true"

J'espère que ça marchera pour vous aussi.

69
répondu drspaceboo 2014-02-24 08:48:01

Enfin je l'ai résolu en faisant une transformation de Picasso, voici l'extrait:

    Transformation transformation = new Transformation() {

        @Override
        public Bitmap transform(Bitmap source) {
            int targetWidth = holder.message_picture.getWidth();

            double aspectRatio = (double) source.getHeight() / (double) source.getWidth();
            int targetHeight = (int) (targetWidth * aspectRatio);
            Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
            if (result != source) {
                // Same bitmap is returned if sizes are the same
                source.recycle();
            }
            return result;
        }

        @Override
        public String key() {
            return "transformation" + " desiredWidth";
        }
    };

    mMessage_pic_url = message_pic_url;

    Picasso.with(this.context)
        .load(message_pic_url)
        .error(android.R.drawable.stat_notify_error)
        .transform(transformation)
        .into(holder.message_picture, new Callback() {
            @Override
            public void onSuccess() {
                holder.progressBar_picture.setVisibility(View.GONE);
            }

            @Override
            public void onError() {
                Log.e(LOGTAG, "error");
                holder.progressBar_picture.setVisibility(View.GONE);
            }
    });

cette ligne est pour personnaliser avec votre largeur souhaitée:

int targetWidth = holder.message_picture.getWidth();

en outre, ce fichier compressé inclut le rappel pour le chargement de cache et le drawable intégré à Picasso.

si vous avez besoin de plus d'informations pour déboguer une erreur, vous devez implémenter un écouteur personnalisé (Picasso builder) pour utiliser le onError Callback l'information est "nulle". Vous savez seulement qu'il y a une erreur de comportement de l'INTERFACE utilisateur.

j'espère que cela aide quelqu'un à sauver de nombreuses heures.

55
répondu wendigo 2015-07-15 08:46:25

Peut Accepté la Réponse est Utile à tous, mais Si vous êtes à la liaison de Plusieurs ViewHolder pour Plusieurs Views , alors vous pouvez réduire votre code par la Création de la Classe pour Transformation et en passant ImageView à partir de ViewHolder .

/**
 * Created by Pratik Butani
 */
public class ImageTransformation {

    public static Transformation getTransformation(final ImageView imageView) {
        return new Transformation() {

            @Override
            public Bitmap transform(Bitmap source) {
                int targetWidth = imageView.getWidth();

                double aspectRatio = (double) source.getHeight() / (double) source.getWidth();
                int targetHeight = (int) (targetWidth * aspectRatio);
                Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
                if (result != source) {
                    // Same bitmap is returned if sizes are the same
                    source.recycle();
                }
                return result;
            }

            @Override
            public String key() {
                return "transformation" + " desiredWidth";
            }
        };
    }
}

appelant de ViewHolder :

Picasso.with(context).load(baseUrlForImage)
                     .transform(ImageTransformation.getTransformation(holder.ImageView1))
                     .error(R.drawable.ic_place_holder_circle)
                     .placeholder(R.drawable.ic_place_holder_circle)
                     .into(holder.mMainPhotoImageView1);

J'espère que ça vous aidera.

8
répondu Pratik Butani 2017-05-23 10:31:25
    Picasso.with(this).load(url).resize(1800, 1800).centerInside().into(secondImageView)

    <ImageView
        android:id="@+id/SecondImage"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:adjustViewBounds="true"
        android:layout_margin="10dp"
        android:visibility="gone"/>

cela vous aidera avec la hauteur variable des images pour tous les dispositifs

2
répondu Kiran 2016-05-31 12:59:12

j'ai écrit simple helper qui prennent soin d'ajouter layout écouteur complet et appeler dans(imageView) lorsque le processus de layout terminé.

public class PicassoDelegate {

private RequestCreator mRequestCreator;

public PicassoDelegate(ImageView target, RequestCreator requestCreator) {
    if (target.getWidth() > 0 && target.getHeight() > 0) {
        complete(target, requestCreator);
    } else {
        mRequestCreator = requestCreator;
        target.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                v.removeOnLayoutChangeListener(this);
                complete((ImageView) v, mRequestCreator);
            }
        });

    }

}

private void complete(ImageView target, RequestCreator requestCreator) {
    if (target.getWidth() > 0 && target.getHeight() > 0) {
        requestCreator.resize(target.getWidth(), target.getHeight());
    }

    requestCreator.into(target);
}

}

donc vous pouvez facilement l'utiliser comme ceci par exemple dans onviewcreated ()

new PicassoDelegate(customerPhoto, Picasso.with(getActivity()).load(user.getPhotoUrl()).centerCrop());
0
répondu Dmytro 2015-09-02 18:35:34
imageView.post(new Runnable() {
      @Override public void run() {
        Picasso.with(context)
            .resize(0, imageView.getHeight())
            .onlyScaleDown()
            .into(imageView, new ImageCallback(callback, null));
      }
    });
0
répondu Igor Bykov 2017-04-24 20:23:41
public class CropSquareTransformation implements Transformation {

  private int mWidth;
  private int mHeight;

  @Override public Bitmap transform(Bitmap source) {
    int size = Math.min(source.getWidth(), source.getHeight());

    mWidth = (source.getWidth() - size) / 2;
    mHeight = (source.getHeight() - size) / 2;

    Bitmap bitmap = Bitmap.createBitmap(source, mWidth, mHeight, size, size);
    if (bitmap != source) {
      source.recycle();
    }

    return bitmap;
  }

  @Override public String key() {
    return "CropSquareTransformation(width=" + mWidth + ", height=" + mHeight + ")";
  }

plus de transformations: https://github.com/wasabeef/picasso-transformations

0
répondu Pablo Cegarra 2017-08-10 07:33:42

étendre ImageView puis outrepasser la méthode onMeasure comme suit.

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
        Drawable d = getDrawable();

        if(d!=null && fittingType == FittingTypeEnum.FIT_TO_WIDTH){
            int width = MeasureSpec.getSize(widthMeasureSpec);
            int height = (int) Math.ceil((float) width * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth());
            setMeasuredDimension(width, height);
        }else{
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
0
répondu Jinichi 2017-11-15 01:36:08

en fait j'étais en train de charger l'image dans CustomImageView qui avait la fonctionnalité zoomable

Erreur était

java.lang.RuntimeException: Transformation transformation desiredWidth crashed with exception.

j'ai résolu cela en éditant le code donné à partir de la réponse acceptée j'ai obtenu la largeur maximale de mon affichage comme si la largeur de mon imageview était déjà match_parent.

if (!imgUrl.equals (" " )) {

        DisplayMetrics displayMetrics = new DisplayMetrics();
        ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        int height = displayMetrics.heightPixels;
        int width = displayMetrics.widthPixels;

        Picasso.with(context).load(imgUrl)
                .transform(getTransformation(width, imageView))
                .into(imageView, new Callback() {
                    @Override
                    public void onSuccess() {
                        if (progressBar != null) {
                            progressBar.setVisibility(View.GONE);
                        }
                    }

                    @Override
                    public void onError() {
                        if (progressBar != null) {
                            progressBar.setVisibility(View.GONE);
                        }
                    }
                });
    }

    public static Transformation getTransformation(final int width, final ImageView imageView) {
        return new Transformation() {
            @Override
            public Bitmap transform(Bitmap source) {
                int targetWidth = width;
                double aspectRatio = (double) source.getHeight() / (double) source.getWidth();
                int targetHeight = (int) (targetWidth * aspectRatio);
                Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
                if (result != source) {
                    // Same bitmap is returned if sizes are the same
                    source.recycle();
                }
                return result;
            }

            @Override
            public String key() {
                return "transformation" + " desiredWidth";
            }
        };
    }
0
répondu Vivek Barai 2018-01-04 05:49:04