How to get the Dimensions of a Drawable in an ImageView? [duplicate]
Asked Answered
G

5

49

What is the best way to retrieve the dimensions of the Drawable in an ImageView?

My ImageView has an Init-Method where I create the ImageView:

private void init() {
    coverImg = new ImageView(context);
    coverImg.setScaleType(ScaleType.FIT_START);
    coverImg.setImageDrawable(getResources().getDrawable(R.drawable.store_blind_cover));
    addView(coverImg);
}

At some point during the layout oder measure process I need the exact dimensions of the Drawable to adjust the rest of my Components around it.

coverImg.getHeight() and coverImg.getMeasuredHeight() don't return the results that I need and if I use coverImg.getDrawable().getBounds() I get the dimensions before it was scaled by the ImageView.

Thanks for your help!

Grill answered 10/1, 2011 at 17:14 Comment(0)
C
54

Just tried this out and it works for me:

int finalHeight, finalWidth;
final ImageView iv = (ImageView)findViewById(R.id.scaled_image);
final TextView tv = (TextView)findViewById(R.id.size_label);
ViewTreeObserver vto = iv.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
    public boolean onPreDraw() {
        // Remove after the first run so it doesn't fire forever
        iv.getViewTreeObserver().removeOnPreDrawListener(this);
        finalHeight = iv.getMeasuredHeight();
        finalWidth = iv.getMeasuredWidth();
        tv.setText("Height: " + finalHeight + " Width: " + finalWidth);
        return true;
    }
});

The ViewTreeObserver will let you monitor the layout just prior to drawing it (i.e. everything has been measured already) and from here you can get the scaled measurements from the ImageView.

Claymore answered 10/1, 2011 at 17:58 Comment(12)
ya it works but after oncreat() load is there any other way that we can get height or position in oncreat()Goldschmidt
I like this solution, and it just about works for my needs. But for some reason onPrewDraw callback doesn't seem to ever stop firing. I simply logged the height and width to make sure. Any idea why?Mismanage
Override the View's onsizeChanged() method. You don't need to add pre-draw listeners.Steady
@Kerry That works only if it's a custom view you wrote yourself.Claymore
onSizechanged() is called whether it's View or a developer's custom View. Either way you can still override it, just call through to the super if it's not a custom view.Steady
@Kerry You can't override that method unless you're subclassing the View.Claymore
It's a pain but there's nothing stopping you doing that.Steady
Sure, it's a solution in some cases when you need to do something with a custom view, but the pre-draw listener is a solution for any view.Claymore
Yes fair point. I should read the question with more care. I withdraw my criticism. Sorry!Steady
@Kerry No problem :) I think that's definitely the better solution for the case where a custom View needs to change how it renders its own content.Claymore
There is a typo in your example: tv.getViewTreeObserver().removeOnPreDrawListener(this); but we should remove listener from "iv" not from "tv".Checkerbloom
This answer is being discussed on meta,Almondeyed
O
50

Call getIntrinsicHeight and getIntrinsicWidth on the drawable.

public int getIntrinsicHeight ()

Since: API Level 1

Return the intrinsic height of the underlying drawable object. Returns -1 if it has no intrinsic height, such as with a solid color.

public int getIntrinsicWidth ()

Since: API Level 1

Return the intrinsic width of the underlying drawable object.

Returns -1 if it has no intrinsic width, such as with a solid color.

http://developer.android.com/reference/android/graphics/drawable/Drawable.html#getIntrinsicHeight()

This is the size of the original drawable. I think this is what you want.

Outgoing answered 13/1, 2011 at 14:28 Comment(6)
I am facing the same problem. But intrinsic height and width are different on different sized devices even though the underlying png is of course the same size! How can that be? Where is the documentation for "intrinsic"?Decay
In fact, looking at Android's source code: these intrinsic values are affected by the target density, so they are definitely NOT the dimensions of the image!Decay
So? What is the trick to get the dimensions of the image then?Bremsstrahlung
@Decay Can you make a reference, because based on experimentation this is the actual dimensions of the original image, in other word the size in dp units NOT px.Turkey
@Decay if you store image with width 120px in xxhdpi folder, intristicWidth will be 120 on xxhdpi device, however it will be 60 on hdpi device. Because autoscaling of course.Scandalmonger
For those coming here in 2023+, @Decay is correct. Here is a full explanation: https://mcmap.net/q/111818/-how-to-access-size-of-android-drawableLafountain
G
24

The most reliable and powerful way to get drawable dimensions for me has been to use BitmapFactory to decode a Bitmap. It's very flexible - it can decode images from a drawable resource, file, or other different sources.

Here's how to get dimensions from a drawable resource with BitmapFactory:

BitmapFactory.Options o = new BitmapFactory.Options();
o.inTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
Bitmap bmp = BitmapFactory.decodeResource(activity.getResources(),
                                               R.drawable.sample_image, o);
int w = bmp.getWidth();
int h = bmp.getHeight();

Be careful if you use multiple density drawable folders under res, and make sure you specify inTargetDensity on your BitmapFactory.Options to get the drawable of the density you want.

Garate answered 18/1, 2012 at 20:52 Comment(3)
I've taken exactly the same values as in Intrinsic values.Bremsstrahlung
Returns the dimensions in dp.Yseulta
Doesn't work for svg files. Sigh.Clipboard
A
11

Efficient way to get Width & Height of Drawable:

Drawable drawable = getResources().getDrawable(R.drawable.ic_home);
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
Log.i("Drawable dimension : W-H", width+"-"+height);

Hope this will help you.

Altaf answered 9/2, 2016 at 12:48 Comment(1)
Returns the dimensions in pixels, depending on the underlying dpi-dependent asset.Yseulta
I
6

this solved my problem. It decode the size of image boundary without really load the whole image.

BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeResource(this.getResources(), R.drawable.img , o);
int w = o.outWidth;
int h = o.outHeight;
Indomitable answered 24/11, 2014 at 0:36 Comment(5)
This answer is an inferior and syntactically incorrect copy of ubzack's answer.Songster
@Songster Thanks for the note :) I just found I didn't paste my complete code. That's why you feel it's copied from others' answer :)Indomitable
OK, but you should add a comma before the last parameter of the decodeResource() method in order to make it syntactically correct.Songster
This is the best answer to this portion of noteme's question: "retrieve the dimensions of the Drawable". It is less resource intensive: refer documentation "Setting the inJustDecodeBounds property to true while decoding avoids memory allocation" developer.android.com/training/displaying-bitmaps/…Vibes
It is definitely less resource intensive, which is an important consideration if the reason you want to resize the image is because you don't want to run in to OutOfMemory errors. However, it does not answer the question - the OP wishes to know the size of the drawable after it has been scaled inside the ImageView. I +1 it in the hope that it might be useful to someone else who landed up at this page to whom getting the actual unscaled drawable's dimensions was sufficient, but frankly, this is not the right answer.Aslam

© 2022 - 2024 — McMap. All rights reserved.