I have a bitmap with the dimensions of 537 * 233. This is displayed in my fragment.
I am calculating the height of this bitmap through code as well.
I came to know that simply using,
image.getHeight() will always return 0.
Then I found that putting the same in overridden method onGlobalLayout() will give the actual height.
I did that. See my SO post for link.
Now the height I am getting is 155.
I also tried getting the height with,
BitmapDrawable bd = (BitmapDrawable) getResources().getDrawable(R.drawable.chart);
imgHeight = bd.getBitmap().getHeight();
Again the height I am getting is 155.
According to the above dimensions, the height should be 233.
I am seeing the same height in emulator too.
Why is the difference and/or what I consider to be its actual height ?
UPDATE:
ok, my chart was in drawable-hdpi and the density of my device is 160. So when I put the chart image in drawable folder, I got the correct height. But then if the chart height is fixed (233), why in some devices I am getting the chart height big enough to overlap my bottom timeline. Although I know a bit that this may be because of approximate values and not accurate values (density, resolution) that is causing the in-differences. But then, Any ideas how to fix that ?
First you know mdpi = 1, hdpi = 1.5 and xhdpi = 2.
Lets say you have an image in mdpi folder with width = 100px.
On mdpi device the image width will be 100x1 = 100px,
On hdpi device 100x1.5 = 150px,
On xhdpi device 100x2 = 200px.
if you dont have the image in hdpi or xhdpi folders the android system will scale them.
So when you have an Image in hdpi folder and you run the app on medium density device (mdpi), the android will scale down the image by 1.5. 233 / 1.5 = 155.
The same will happend if run the app to hdpi device you will get an image with ~310 width.
So, to avoid the scaling i suggest to put the image in drawable-nodpi folder (the images in this folder will not scaled by android system).
PS: if you put the image in drawable folder and run in mdpi device the image will not scaled because drawable folder = drawable-mdpi
Related
Although this question is not related to programming, it is related to app development.
Suppose I have an ImageView whose dimensions are 40dp*40dp. If I use the above formula to create an icon for a device with screen density 217 ppi, the size of the icon that fits the ImageView exactly is 55px*55px. If I use this icon in the view in consideration, the result is that the icon does not appear very sharp.
On the other hand, if I use a larger image of size, say 80px*80px, it appears sharp. So this larger image is larger than the exactly fitting one by a factor of 1.6.
What I would like to know is whether there is a certain value of the above factor that is most efficient and conventional. I would like to follow conventions while developing my apps.
Thanks for your time.
Your ImageView size is 40dp, thats equal to:
40 x 1.0 = 40 pixel on mdpi devices
40 x 1.5 = 60 pixel on hdpi devices
40 x 2.0 = 80 pixel on xhdpi devices
40 x 3.0 = 120 pixel on xxhdpi devices
40 x 4.0 = 160 pixel on xxxhdpi devices
Now your device is hdpi (217). for thats device you need a 60x60 pixel bitmap, and you have to put it in the drawable-hdpi directory.
Using drawable directory is like using drawable-mdpi directory. fro each resource in that directory android will scale it up/down before using it.
I am having a big trouble in resizing my images for Android image sizes, ldpi (120 dpi), mdpi(160 dpi), hdpi(240dpi), xhdpi(320 dpi) and nodpi using Photoshop, because I don't know how to convert my images to these size. As you know, Photoshop has no DPI stuff to work with. So, what I actually need is to convert my images to ldpi,mdpi,hdpi and xhdpi sizes using Photoshop.
So, how can I convert these images to the Android deserved sizes?
Have you tried using Illustrator? The psd files can also be worked with it.
You could also use Inkscape or other free tools.
Check this: http://envyandroid.com/archives/271/easiest-way-to-create-android-icons
Hope this helps.
The answer is right there in your screenshot. Photoshop uses Pixels/Inch which is the same as DPI (well mostly, anyway).
To achieve what you are trying to do, simply alter the Pixels/Inch in the Image Size dialog to your DPI value - start with 320dpi, since shrinking images will look better than enlarging them. After altering the value you will notice that your width and height values (Pixel Dimensions) are changed, change them back to the desired resolution for your 320dpi image (make sure that you use a sufficiently large resolution for 320dpi).
Now create your image for this resolution. Once you are complete, open the Image Size dialog again. Now all you need to do is alter the Pixels/Inch value to the remaining DPI values (240, 160, 120) and your image will be scaled down (notice how the width and height for Pixel Dimensions will get smaller with each decrease in DPI).
If you have no idea about the starting resolution you can use the width and height under Document Size to set the actual resolution. For example, the Nexus 4 is a 320ppi device (mostly) and has a screen size of 4.7" (5.27x x 2.70x), so if you use a width of 2.635" and a height of 1.35" it should cover 1/4 of it's screen (half of width and half of height).
I am using image say 85x85 px (putting this image in drawable-mdpi)
and if i am displaying this image of 85x85 px on [320x480]mdpi screen size device it looks good,
but while displaying this image on [480x800]mdpi device it looks very small.
I wants to know how can i resize this image of (85x85 px) so that it works fine for the device having screen width and height of 480x800, mdpi.
You have to set the image size in the xml in dp. This post is really helpful.
Consider MDPI image(let say 85x85) as baseline Create images as follow
FOLDER ImageSize Percentage
LDPI 64x64 75% of baseline
MDPI 85x85 100% BASELINE
HDPI 127x127 150% of baseline
XHDPI 170x170 200% of baseline
The better solution for this is to produce LDPI,MDPI,HDPI,XHDPI,XXHDPI sized images and place it inside the corresponding folders.
Put the image in /drawable, and define the size of the image in your XML as 85dp, it will then be scaled for LDPI/HDPI/XHDPI/XXHDPI and god forbid XXXHDPI.
However, the better solution would to produce HDPI(128px)/XHDPI(170px)/XXHDPI(255px) version of the graphics and put them in /drawable-hdpi, /drawable-xhdpi, /drawable-xxhdpi respectively. This way you can provide the best experience for your users.
[Edit]
"dp" is Android's way of defining physical size of an UI objects, so a button of 48x48dp will have roughly the same physical dimension even when run on screen sizes between 240x320 to 1080x1920, for more information check Android developer site's Supporting Multiple Screens.
[Edit 2]
For images on canvas you can use this to calculate the scaled size of the image:
DisplayMetrics dm = new DisplayMetrics();
context.getWindowManager().getDefaultDisplay().getMetrics(dm);
int newSize = (int)(85 * (dm.densityDpi / 160f));
Is it possible to use common hdpi folder for all screen densities? I have quite a lot images. If I make specific copies to folders drawable-hdpi, drawable-ldpi, drawable-xhdpi, ... but it takes huge data (backgrounds, bitmaps).
Is it possible to set only one drawable folder for all devices and then rescale according to a specific device programmatically?
I think about this code to get display size of the scree:
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth();
height = display.getHeight();
Then I will get display density of the device, something like this:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
density = metrics.density; // 1 - 1,5 - 2 .....
The I will recalculate size of imageview with density:
ImageView logo = (ImageView)findViewById(R.id.logo);
LinearLayout.LayoutParams logo1 = (LinearLayout.LayoutParams) logo.getLayoutParams();
logo1.width = (int)(logo.getWidth()*density);
logo1.height = (int)(logo.getHeight()*density);
logo1.leftMargin=(int)(logo1.leftMargin*density); // for margin
logo1.topMargin=(int)(logo1.topMargin*density); // for margin
logo1.rightMargin=(int)(logo1.rightMargin*density); // for margin
logo1.bottomMargin=(int)(logo1.bottomMargin*density); // for margin
My main problem is I need to have all proportions of graphic same on all devices. It means I must recalculate imageViews accroding to the screen size.
Is this a right way to get density independent screen? How does android work on other devices if only hdpi folder contains files. Does it take files from this folder? Can I set one common drawable folder to all densities?
I would strongly (strongly) advise against doing this. However, if you want the system to rescale your image assets, design them for mdpi (the baseline density) and put them in drawable/.
That said, you need at least mdpi and hdpi to get reasonable scaling (since hdpi is 1.5x mdpi, scaling algorithms produce worse results than for the other conversions from mdpi).
Make sure you've read and understood Providing Resources and Supporting Multiple Screens before you start dealing with resources.
P.S. The layout solution is wrong for a few reasons (e.g., setting margins instead of size) but it's also the completely wrong thing to do. Don't do it!
Should be a simple one.
When I pull image.getDrawable().getIntrinsicWidth() I get a value larger than the source image width. It's X coordinate is returning 2880 instead of 1920 which is 1.5 times too big?
I wondered wether the ImageView having a scaleType of "center" effected it but, according to the documentation:
"Center the image in the view, but perform no scaling."
Here is the source:
<ImageView
android:id="#+id/backgroundImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/background"
android:scaleType="center"/>
You said the drawable is from your /res folder. Which folder is it in?
/res/drawable
/res/drawable-mdpi
/res/drawable-hdpi
etc..
And what is the density of the device you are testing on? Is it a Nexus S with general density of 240dpi? Because if your source drawable is located in the drawable-mdpi folder and you are testing on a 240dpi device, then the Android system will automatically scale the drawable up by a factor of 1.5 so that the physical size will be consistent with the baseline device density at 160dpi.
When you call getIntrinsicWidth() what is returned is the size the drawable wants to be after Android scales the drawable. You'll notice that 2880 = 1920 * 1.5
If you placed the drawable in /res/drawable the Android system treats those drawables as meant for mdpi devices, thus the upscaling in your Nexus S. If this was meant for hdpi screens and you do not want this to upscale then try placing it in drawable-hdpi
Have you tried to multiply height and width by density:
getResources().getDisplayMetrics().density
Is your drawable in ressources or download from the web? If it is downloaded, you have to give it the density:
DisplayMetrics metrics = new DisplayMetrics();
getContext().getWindowManager().getDefaultDisplay().getMetrics(metrics);
Resources r = new Resources(getContext().getAssets(), metrics, null);
BitmapDrawable bmd = new BitmapDrawable(r, bitmap);
Check if it is returning the value of it's displayed size, which is not it's actual size. For example, a 50x320px banner ad on a traditional 800x480 phone displays as 75x480.
Should be able to compare against density (or your eyes!) to see what it is doing.
This is probably going to be nothing to with the issue you're having, but just for kicks I'll suggest it to be sure anyway: Are you specifying android:minSdkVersion in your manifest?
Only reason I mention this is because for a while I wasn't doing so in a project, and I learned that this screws the screen density up and caused all sorts of strange problems.