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.
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);
}
});
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.
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.
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.
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
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());
imageView.post(new Runnable() {
@Override public void run() {
Picasso.with(context)
.resize(0, imageView.getHeight())
.onlyScaleDown()
.into(imageView, new ImageCallback(callback, null));
}
});
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
é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);
}
}
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";
}
};
}