Image beyond borders after conversion to view

I have a problem displaying my image.

I have an image that I want to display in full screen. So I have this Imageview with match_parent and 20dp padding.

enter image description here

It looks good, but when I apply a rotation to it, it seems that the borders of the view do not change, and the image can be cut from the screen! I totally don't want this to happen! How to resize the image so that the image also fits into the ImageView when rotated 90 degrees.

enter image description here

This is my XML WITH rotation.

enter image description here

EDIT:

How to fix image borders so that text aligns just above the image? enter image description here

+3
android rotation view imageview bounds
source share
4 answers

Rotation is not taken into account when measuring the view and calculating the scaling factor. A possible solution is to do it yourself:

public class RotatedImageView extends ImageView { ... constructors ... private double mRotatedWidth; private double mRotatedHeight; private boolean update() { Drawable d = getDrawable(); if (d == null) { return false; } int drawableWidth = d.getIntrinsicWidth(); int drawableHeight = d.getIntrinsicHeight(); if (drawableWidth <= 0 || drawableHeight <= 0) { return false; } double rotationRad = getRotation() / 180 * Math.PI; // calculate intrinsic rotated size // see diagram mRotatedWidth = (Math.abs(Math.sin(rotationRad)) * drawableHeight + Math.abs(Math.cos(rotationRad)) * drawableWidth); mRotatedHeight = (Math.abs(Math.cos(rotationRad)) * drawableHeight + Math.abs(Math.sin(rotationRad)) * drawableWidth); return true; } protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (update()) { double ratio = mRotatedWidth / mRotatedHeight; int wMax = Math.min(getDefaultSize(Integer.MAX_VALUE, widthMeasureSpec), getMaxWidth()); int hMax = Math.min(getDefaultSize(Integer.MAX_VALUE, heightMeasureSpec), getMaxHeight()); int w = (int) Math.min(wMax, hMax * ratio); int h = (int) Math.min(hMax, wMax / ratio); setMeasuredDimension(w, h); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } private final float[] values = new float[9]; protected void onDraw(Canvas canvas) { if (update()) { int availableWidth = getMeasuredWidth(); int availableHeight = getMeasuredHeight(); float scale = (float) Math.min(availableWidth / mRotatedWidth, availableHeight / mRotatedHeight); getImageMatrix().getValues(values); setScaleX(scale / values[Matrix.MSCALE_X]); setScaleY(scale / values[Matrix.MSCALE_Y]); } super.onDraw(canvas); } @Override public void setRotation(float rotation) { super.setRotation(rotation); requestLayout(); } } 

adjustViewBounds should be true:

 <com.mypackage.RotatedImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="20dp" android:adjustViewBounds="true" android:rotation="90" android:maxWidth="100dp" android:maxHeight="100dp" android:scaleType="fitCenter" android:src="@drawable/test" /> 

A good calculation explanation, courtesy of Cheticamp :

enter image description here

rotation =

rotation =

rotation =

UPDATE: Now we are trying to set the boundaries. There is no difference between wrap_content and match_parent (both grow as much as possible based on the aspect of the image). Instead, use maxWidth and / or maxHeight , or put it in a LinearLayout with a size and weight of 0.

It also does not animate, adjusting the boundaries, and the animation requires a layout for each frame, which is very inefficient. See Another answer for the version used with View.animate()

+5
source share

Another version of RotatedImageView, the rotation of which can be animated using ViewPropertyAnimator . The idea is the same, but scaling is done in onDraw() instead of onMeasure() , so it doesn't need a layout every time. To make the animation, I had to grab an update listener. If you want to use your own listener, don't forget to invalidate() look in onAnimationUpdate() .

 public class RotatedImageView2 extends ImageView { ... constructors ... protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int beforeWidth = getMeasuredWidth(); int beforeHeight = getMeasuredHeight(); int max = Math.max(beforeWidth, beforeHeight); // try to grow setMeasuredDimension(getDefaultSize(max, widthMeasureSpec), getDefaultSize(max, heightMeasureSpec)); } private final float[] values = new float[9]; @Override protected void onDraw(Canvas canvas) { Drawable d = getDrawable(); if (d == null) { return; } int drawableWidth = d.getIntrinsicWidth(); int drawableHeight = d.getIntrinsicHeight(); if (drawableWidth <= 0 || drawableHeight <= 0) { return; } double rotationRad = getRotation() / 180 * Math.PI; double rotatedWidth = (Math.abs(Math.sin(rotationRad)) * drawableHeight + Math.abs(Math.cos(rotationRad)) * drawableWidth); double rotatedHeight = (Math.abs(Math.cos(rotationRad)) * drawableHeight + Math.abs(Math.sin(rotationRad)) * drawableWidth); int availableWidth = getMeasuredWidth(); int availableHeight = getMeasuredHeight(); float scale = (float) Math.min(availableWidth / rotatedWidth, availableHeight / rotatedHeight); getImageMatrix().getValues(values); setScaleX(scale / values[Matrix.MSCALE_X]); setScaleY(scale / values[Matrix.MSCALE_Y]); super.onDraw(canvas); } @Override public void setRotation(float rotation) { super.setRotation(rotation); // force redraw invalidate(); } @Override public ViewPropertyAnimator animate() { // force redraw on each frame // (a ViewPropertyAnimator does not use setRotation()) return super.animate().setUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { invalidate(); } }); } } 

Usage example:

 <com.mypackage.RotatedImageView2 android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="20dp" android:adjustViewBounds="true" android:rotation="90" android:scaleType="fitCenter" android:src="@drawable/test" /> 
+1
source share

according to research leading to this topic , I am wondering if @Sarge Borsch can answer in your case.

Try to install

 android:scaleType="centerInside" android:adjustViewBounds="true" 

If centerInside is incorrect because you want to display in the center, perhaps try positioning the image instead of the image inside.

Another suggestion: your image will be set to "wrap_content", and I don’t know the order of everything, but maybe the problem arises because it rotates after calculating the measurements (due to wrap_content). I think this is possible because the screenshot you put shows that the image does not even fit the width. TL; DR: try to fix the image size (padding on activity + match_parent) instead of wrapping the content in combination with the "adjustViewBounds" parameter.

0
source share

The android:rotation attribute refers to the view, which is an ImageView, not its contents.

If you want to rotate the content, either set the new BItmap as the content, or override onDraw() and rotate the canvas

0
source share

All Articles