21

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).

Manuel Allenspach
  • 12,467
  • 14
  • 54
  • 76
Freewind
  • 193,756
  • 157
  • 432
  • 708
  • you can use ViewTreeObserver to get the real dimensions of any view at run time http://developer.android.com/reference/android/view/ViewTreeObserver.html – Arpit Garg Sep 17 '12 at 16:23
  • Thanks, I'm looking at it. PS: is it the best/only way to get the size? – Freewind Sep 17 '12 at 16:33
  • 1
    Sorry, even with ViewTreeObserver, I still don't know how to get the **displayed** size of the image. – Freewind Sep 17 '12 at 16:37
  • possible duplicate of [Trying to get the display size of an image in an ImageView](http://stackoverflow.com/questions/3855218/trying-to-get-the-display-size-of-an-image-in-an-imageview) – btalb Mar 20 '14 at 01:52

4 Answers4

56

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);
SMR
  • 6,628
  • 2
  • 35
  • 56
fsegaux
  • 592
  • 4
  • 3
8

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;
}
Nabin Bhandari
  • 15,949
  • 6
  • 45
  • 59
0

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.

ueen
  • 692
  • 3
  • 9
  • 21
  • 1
    Actually, I am coming from an OCR library that returns the placements of words relative to the original image and I have to position them on a scaled `ImageView`. Your origin story was nice, though. – Abandoned Cart Feb 26 '20 at 15:24
-1

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();
RajeshVijayakumar
  • 10,281
  • 11
  • 57
  • 84