Изменение размера изображения до полной ширины и переменной высоты с помощью Picasso
У меня есть listView с адаптером, который содержит ImageView
с переменным размером (ширина и высота). Мне нужно resize изображения с Picasso до максимальной ширины макета и переменной высоты, определяемой соотношением сторон изображения.
Я проверил этот вопрос: измените размер изображения на всю ширину и фиксированную высоту с помощью Picasso
Работа fit()
работает, но я не нашел ничего, чтобы сохранить соотношение сторон изображения.
- Использование библиотеки Picasso с ListView
- Как реализовать мой собственный кэш диска с библиотекой picasso - Android?
- Пикассо загружает ресурсы с их URI
- Библиотека Android Picasso, Как добавить заголовки аутентификации?
- Загрузка Picasso изображения, созданного внутри AsyncTask
Этот код частично работает, если я исправил высоту в макете адаптера:
Picasso.with(this.context).load(message_pic_url) .placeholder(R.drawable.profile_wall_picture) .fit().centerInside() .into(holder.message_picture);
Но он создает пробелы между изображениями listView, потому что изображения могут быть такими, которые не имеют этой высоты.
Заранее спасибо.
- Picasso Загрузить изображение из файловой системы
- android: создать круговое изображение с пикассо
- Recyclerview мучительно медленно загружает кешированные изображения из Picasso
- Как использовать кеширование диска в Picasso?
- Загрузка больших изображений с помощью Picasso и настраиваемого объекта Transform
- onBitmapLoaded объекта Target, не вызванного первой загрузкой
- Android: загружено изображение Picasso. как показать сообщение об ошибке
- Используйте Picasso для получения обратного вызова с помощью Bitmap
Начиная с 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"; } }; }