Изменение размера изображения до полной ширины и переменной высоты с помощью Picasso

У меня есть listView с адаптером, который содержит ImageView с переменным размером (ширина и высота). Мне нужно resize изображения с Picasso до максимальной ширины макета и переменной высоты, определяемой соотношением сторон изображения.

Я проверил этот вопрос: измените размер изображения на всю ширину и фиксированную высоту с помощью Picasso

Работа fit() работает, но я не нашел ничего, чтобы сохранить соотношение сторон изображения.

Этот код частично работает, если я исправил высоту в макете адаптера:

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

Но он создает пробелы между изображениями listView, потому что изображения могут быть такими, которые не имеют этой высоты.

Заранее спасибо.

Начиная с Picasso 2.4.0, эта операция теперь напрямую поддерживается . Просто добавьте .resize() с одним из размеров как 0 . Например, чтобы иметь переменную ширину, ваш вызов станет следующим:

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

Обратите внимание, что этот вызов использует .getHeight() и поэтому предполагает, что message_picture уже измерен. Если это не так, например, когда вы надули новое представление в ListAdapter , вы можете отложить этот вызов до тех пор, пока не OnGlobalLayoutListener измерение, добавив OnGlobalLayoutListener в представление:

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

Я столкнулся с одной проблемой, и мне потребовалось некоторое время, чтобы найти решение, но я, наконец, наткнулся на то, что работает для меня.

Во-первых, я изменил вызов Пикассо

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

Удаление fit и центра. Затем вам нужно добавить следующие строки в ImageView в XML

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

Надеюсь, это сработает и для вас.

Наконец, я решил, что он делает преобразование Пикассо, вот fragment:

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

Эта строка предназначена для настройки с нужной шириной:

 int targetWidth = holder.message_picture.getWidth(); 

Кроме того, этот снимок включает в себя обратный вызов для загрузки скрытого и исправляемого ошибок встроенного Picasso.

Если вам нужна дополнительная информация для отладки какой-либо ошибки, вы ДОЛЖНЫ реализовать пользовательский прослушиватель (построитель Picasso), onError информация об onError имеет значение «null». Вы только знаете, что существует ошибка для поведения пользовательского интерфейса.

Надеюсь, это поможет кому-то сэкономить много часов.

May Accepted Answer Полезен для всех, но если вы привязываете несколько ViewHolder для нескольких Views вы можете уменьшить свой код, ViewHolder class для трансформации и передав ImageView из 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"; } }; } } 

Вызов из 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); 

Надеюсь, это поможет вам.

  Picasso.with(this).load(url).resize(1800, 1800).centerInside().into(secondImageView)  

Это поможет вам с переменной высотой изображений для всех устройств

Я написал простой помощник, который заботится о том, чтобы добавить полноэкранный макет и вызвать (imageView), когда процесс компоновки завершен.

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

}

Таким образом, вы можете легко использовать его так, например, в 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 + ")"; } 

Больше преобразований: https://github.com/wasabeef/picasso-transformations

расширение ImageView затем переопределяет метод onMeasure следующим образом.

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

На самом деле я попадал во время загрузки изображения в CustomImageView с масштабируемой функциональностью

Ошибка была

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

Я решил это, отредактировав код, полученный из принятого ответа, и получил максимальную ширину моего дисплея, как если бы моя ширина изображения была уже 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"; } }; } 
  • Зачем использовать библиотеку Android Picasso для загрузки изображений?
  • Давайте будем гением компьютера.