The code is simple:
<ImageView android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="@drawable/cat"/>
Notice the ImageView used fill_parent
for width and height.
The image cat
is a small image and it will be zoomed in to fit the ImageView, and keep the width/height ratio at the same time.
My question is how to get the displayed size of the image? I tried:
imageView.getDrawable().getIntrinsicHeight()
But which it the original height of the image cat
.
I tried:
imageView.getDrawable().getBounds()
But which returns Rect(0,0,0,0)
.
the following will work:
ih=imageView.getMeasuredHeight();//height of imageView
iw=imageView.getMeasuredWidth();//width of imageView
iH=imageView.getDrawable().getIntrinsicHeight();//original height of underlying image
iW=imageView.getDrawable().getIntrinsicWidth();//original width of underlying image
if (ih/iH<=iw/iW) iw=iW*ih/iH;//rescaled width of image within ImageView
else ih= iH*iw/iW;//rescaled height of image within ImageView
(iw x ih) now represents the actual rescaled (width x height) for the image within the view (in other words the displayed size of the image)
EDIT: I think a nicer way to write the above answer (and one that works with ints) :
final int actualHeight, actualWidth;
final int imageViewHeight = imageView.getHeight(), imageViewWidth = imageView.getWidth();
final int bitmapHeight = ..., bitmapWidth = ...;
if (imageViewHeight * bitmapWidth <= imageViewWidth * bitmapHeight) {
actualWidth = bitmapWidth * imageViewHeight / bitmapHeight;
actualHeight = imageViewHeight;
} else {
actualHeight = bitmapHeight * imageViewWidth / bitmapWidth;
actualWidth = imageViewWidth;
}
return new Point(actualWidth,actualHeight);
Here is a helper function to get the bounds of image in an imageView.
/**
* Helper method to get the bounds of image inside the imageView.
*
* @param imageView the imageView.
* @return bounding rectangle of the image.
*/
public static RectF getImageBounds(ImageView imageView) {
RectF bounds = new RectF();
Drawable drawable = imageView.getDrawable();
if (drawable != null) {
imageView.getImageMatrix().mapRect(bounds, new RectF(drawable.getBounds()));
}
return bounds;
}
I guess a lot of people are coming from this example https://developer.android.com/training/animation/zoom.html and don't want to use android:scaleType="centerCrop"
(maybe because the ImageView is in a constraint layout and you want to see the small picture uncroped) don't you worry, I got your back!
Just replace the entire block beginning with
// Adjust the start bounds to be the same aspect ratio as the final
// bounds using the "center crop" technique.
with the following
//adjust for scaled image to constraint
int realheight = ResourcesCompat.getDrawable(getResources(),imageResId,null).getIntrinsicHeight();
int realwidth = ResourcesCompat.getDrawable(getResources(),imageResId,null).getIntrinsicWidth();
// Adjust the start bounds to be the same aspect ratio as the final
// bounds using ueen's adjusteddimensions technique. This prevents undesirable
// stretching during the animation. Also calculate the start scaling
// factor (the end scaling factor is always 1.0).
float startScale;
if ((float) finalBounds.width() / finalBounds.height()
> (float) startBounds.width() / startBounds.height()) {
// Extend start bounds horizontally
// after check whether height or width needs adjusting
if ((float) startBounds.width() / startBounds.height() < (float) realwidth / realheight) {
int adjustedheight = realheight*startBounds.width()/realwidth;
int adjustedoffset = (startBounds.height()-adjustedheight) / 2;
startScale = (float) adjustedheight / finalBounds.height();
float startWidth = startScale * finalBounds.width();
float deltaWidth = (startWidth - startBounds.width()) / 2;
startBounds.left -= deltaWidth;
startBounds.right += deltaWidth;
startBounds.offset(+0, +adjustedoffset);
} else {
int adjustedwidth = realwidth*startBounds.height()/realheight;
int adjustedoffset = (startBounds.width()-adjustedwidth) / 2;
startScale = (float) startBounds.height() / finalBounds.height();
float startWidth = startScale * finalBounds.width();
float deltaWidth = (startWidth - adjustedwidth) / 2;
startBounds.left -= deltaWidth;
startBounds.right += deltaWidth;
startBounds.offset(+adjustedoffset, +0);
}
} else {
// Extend start bounds vertically
// after check whether height or width needs adjusting
if ((float) startBounds.width() / startBounds.height() > (float) realwidth / realheight) {
int adjustedwidth = realwidth*startBounds.height()/realheight;
int adjustedoffset = (startBounds.width()-adjustedwidth) / 2;
startScale = (float) adjustedwidth / finalBounds.width();
float startHeight = startScale * finalBounds.height();
float deltaHeight = (startHeight - startBounds.height()) / 2;
startBounds.top -= deltaHeight;
startBounds.bottom += deltaHeight;
startBounds.offset(+adjustedoffset, +0);
} else {
int adjustedheight = realheight*startBounds.width()/realwidth;
int adjustedoffset = (startBounds.height()-adjustedheight) / 2;
startScale = (float) startBounds.width() / finalBounds.width();
float startHeight = startScale * finalBounds.height();
float deltaHeight = (startHeight - adjustedheight) / 2;
startBounds.top -= deltaHeight;
startBounds.bottom += deltaHeight;
startBounds.offset(+0, +adjustedoffset);
}
}
works like a charme,
you're welcome :)
Further explanation: as usual we check wheter the picture is taller than wide (expanded the height of the picture should match the height of expandedImageView) or vice versa. Then we check if the picture in the original (smaller) ImageView (thumbView) is matching the width or the heigth, so we can adjust for the space.
This way we achieve a smooth scaling animation while not croping the picture in the thumbView, no matter it's dimension (as they may change from device to device when using constarints) or that of the picture.
use
// For getting imageview height
imgObj.getMeasuredHeight()
// For getting imageview width
imgObj.getMeasuredWidth();
//For getting image height inside ImageView
imgObj.getDrawable().getIntrinsicHeight();
//For getting image width inside ImageView
imgObj.getDrawable().getIntrinsicWidth();