Изменение размера изображения до полной ширины и переменной высоты с помощью Picasso
У меня есть listView с адаптером, который содержит ImageView
переменного размера (ширина и высота). Мне нужно изменить размер загрузки изображений с помощью Picasso до максимальной ширины макета и переменной высоты, заданной соотношением сторон изображения.
Я проверил этот вопрос:
Изменение размера изображения до полной ширины и фиксированной высоты с помощью Picasso
Работает fit()
, но я не нашел ничего, чтобы сохранить соотношение сторон изображения.
Этот код частично работает, если я исправил высоту в макете адаптера:
Picasso.with(this.context).load(message_pic_url)
.placeholder(R.drawable.profile_wall_picture)
.fit().centerInside()
.into(holder.message_picture);
Но он создает пробелы между изображениями listView, потому что изображения могут быть такими, которые не имеют этой высоты.
Спасибо заранее.
Ответы
Ответ 1
Наконец, я решил это сделать преобразование Пикассо, вот фрагмент:
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
Callback
равна "null". Вы знаете только, что для поведения пользовательского интерфейса существует ошибка.
Я надеюсь, что это поможет кому-то сэкономить много часов.
Ответ 2
Начиная с 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
:
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);
}
});
Ответ 3
Я столкнулся с той же проблемой, и мне потребовалось некоторое время, чтобы найти решение, но я, наконец, натолкнулся на то, что работает для меня.
Во-первых, я изменил вызов Пикассо на
Picasso.with(this.context).load(message_pic_url)
.placeholder(R.drawable.profile_wall_picture)
.into(holder.message_picture);
Удаление fit
и centerInside
. Затем вам нужно добавить следующие строки в ImageView в свой XML
android:scaleType="fitStart"
android:adjustViewBounds="true"
Надеюсь, это сработает и для вас.
Ответ 4
May Принято Ответ полезен для всех, но если вы привязываетесь Несколько 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);
Надеюсь, это поможет вам.
Ответ 5
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"/>
Это поможет вам с переменной высотой изображений для всех устройств.
Ответ 6
Я написал простого помощника, который заботится о том, чтобы добавить полноэкранный макет и вызвать (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());
Ответ 7
imageView.post(new Runnable() {
@Override public void run() {
Picasso.with(context)
.resize(0, imageView.getHeight())
.onlyScaleDown()
.into(imageView, new ImageCallback(callback, null));
}
});
Ответ 8
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
Ответ 9
расширяйте 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);
}
}
Ответ 10
На самом деле я попадал во время загрузки изображения в 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";
}
};
}
Ответ 11
Picasso.get()
.load(message_pic_url)
.fit()
.centerCrop()
.placeholder(R.drawable.profile_wall_picture)
.into(holder.message_picture);
Попробуйте этот код, Работайте для меня.