Изменение размера изображения до полной ширины и переменной высоты с Пикассо
у меня есть listView с адаптером, который содержит ImageView
переменного размера (ширина и высота). Мне нужно изменить размер загрузки изображений с Picasso до максимальной ширины макета и переменной высоты, заданной соотношением сторон изображения.
Я проверил этот вопрос: Измените размер изображения на полную ширину и фиксированную высоту с помощью Picasso
The fit()
работает, но я не нашел ничего, чтобы сохранить пропорции изображения.
этот код частично работает, если я исправлена высота в компоновке адаптера:
Picasso.with(this.context).load(message_pic_url)
.placeholder(R.drawable.profile_wall_picture)
.fit().centerInside()
.into(holder.message_picture);
но он генерирует пробелы между изображениями listView, потому что изображения могут быть, которые не имеют такой высоты.
спасибо заранее.
10 ответов:
начиная с Пикассо 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
вид: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
иcenterInside
. Далее вам нужно добавить следующие строки в ImageView в вашем XMLandroid:scaleType="fitStart" android:adjustViewBounds="true"
надеюсь, это будет работать для вас также.
наконец я решил это сделать преобразование Пикассо, вот фрагмент:
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();
кроме того, это обрезается включают обратный вызов для загрузки скрыть и ошибки drawable встроенный Picasso.
Если вам нужна дополнительная информация для отладки любой ошибки, вы должны реализовать пользовательский прослушиватель (Picasso builder) beacuse
onError
Callback
информация "null". Вы только знаете, что есть ошибка для поведения пользовательского интерфейса.Я надеюсь, что это поможет кому-то сэкономить много часов.
мая принят ответ полезен для всех, но если вы связываете несколько
ViewHolder
за несколькоViews
затем вы можете уменьшить свой код, создав класс для трансформация и проходя мимо 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 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"/>
Это поможет вам с переменной высотой изображения для всех устройств
Я написал простой помощник, который заботится о добавлении макета полного слушателя и вызова в(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.
Я решил это путем редактирования кода, данного из принятого ответа я получил максимальную ширину моего дисплея, как если бы моя ширина imageview уже была match_parent.
Если (!imgurl на панели.равно ("")) {
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"; } }; }