Set max width for uploading images with Picasso
I have a fixed header in my activity that I need to dynamically load images into it. I need these images to fill this header completely, keep the width and height proportions.
If I load the image before, I get an OutOfMemoryException. If I use Picasso's fit () method, there will be white space in the area. And if I use Transformation as some people on StackOverflow have suggested, I also get an OutOfMemoryException.
How can I solve this?
XML header:
<FrameLayout
android:id="@+id/headerContainer"
android:layout_width="match_parent"
android:layout_height="140dp"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:background="#ffd5d5d5">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView4"
android:layout_gravity="center"
android:src="@drawable/background_camera" />
<ViewFlipper
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/viewFlipper"
android:layout_gravity="center" >
</ViewFlipper>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Adicionar foto do estacionamento"
android:id="@+id/textAddPhotos"
android:layout_gravity="center"
android:textColor="#ff757575"
android:padding="10dp" />
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:id="@+id/addPhotosArea"></RelativeLayout>
</FrameLayout>
Images are added to the ViewFlipper programmatically using the following code:
final ImageView imageView = new ImageView(SuggestionActivity.this);
imageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
Picasso.with(SuggestionActivity.this).load(selectedImageUri)
.fit().centerInside()
.into(imageView);
mViewFlipper.addView(imageView);
UPDATE
I figured out that Picasso was calculating the size incorrectly when loading an image with exif = 90º orientation.
I'm trying to change its source, but the logic is pretty confusing.
I think the problem is with this function of the BitmapHunter.java file:
static Bitmap transformResult(Request data, Bitmap result, int exifRotation) {
int inWidth = result.getWidth();
int inHeight = result.getHeight();
int drawX = 0;
int drawY = 0;
int drawWidth = inWidth;
int drawHeight = inHeight;
Matrix matrix = new Matrix();
if (data.needsMatrixTransform()) {
int targetWidth = data.targetWidth;
int targetHeight = data.targetHeight;
float targetRotation = data.rotationDegrees;
if (targetRotation != 0) {
if (data.hasRotationPivot) {
matrix.setRotate(targetRotation, data.rotationPivotX, data.rotationPivotY);
} else {
matrix.setRotate(targetRotation);
}
}
if (data.centerCrop) {
float widthRatio = targetWidth / (float) inWidth;
float heightRatio = targetHeight / (float) inHeight;
float scale;
if (widthRatio > heightRatio) {
scale = widthRatio;
int newSize = (int) Math.ceil(inHeight * (heightRatio / widthRatio));
drawY = (inHeight - newSize) / 2;
drawHeight = newSize;
} else {
scale = heightRatio;
int newSize = (int) Math.ceil(inWidth * (widthRatio / heightRatio));
drawX = (inWidth - newSize) / 2;
drawWidth = newSize;
}
matrix.preScale(scale, scale);
} else if (data.centerInside) {
float widthRatio = targetWidth / (float) inWidth;
float heightRatio = targetHeight / (float) inHeight;
float scale = widthRatio < heightRatio ? widthRatio : heightRatio;
matrix.preScale(scale, scale);
} else if (targetWidth != 0 && targetHeight != 0 //
&& (targetWidth != inWidth || targetHeight != inHeight)) {
// If an explicit target size has been specified and they do not match the results bounds,
// pre-scale the existing matrix appropriately.
float sx = targetWidth / (float) inWidth;
float sy = targetHeight / (float) inHeight;
matrix.preScale(sx, sy);
}
}
if (exifRotation != 0) {
matrix.preRotate(exifRotation);
}
Bitmap newResult =
Bitmap.createBitmap(result, drawX, drawY, drawWidth, drawHeight, matrix, true);
if (newResult != result) {
result.recycle();
result = newResult;
}
return result;
}
Use .fit (). centerCrop (), it should do what you are looking for.
Before loading the image, the ImageView must be added to the ViewFlipper. This is so that Picasso knows the height / width of the ImageView, which should scale the image properly to the size of the ImageView.
Change it to:
final ImageView imageView = new ImageView(SuggestionActivity.this);
imageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
mViewFlipper.addView(imageView);
Picasso.with(SuggestionActivity.this).load(selectedImageUri)
.fit().centerInside()
.into(imageView);