i'm working on application that have top image in all forms.
i designed the image correctly but to be in top i should set scale type= "fitstart" to be truly be in top.
but the problem is when screen rotates or when app run in bigger screen the image wont stretch in horizon. i think my problem is the imageview size. and it's not just in size of my image and it have blank top and buttons.
how i can solve this problem and what should be the image property. with regards
For this you need to maintain your images in different folders in
res/drawable-mdpi/your_image.png // bitmap for medium density
res/drawable-hdpi/your_image.png // bitmap for high density
res/drawable-xhdpi/your_image.png // bitmap for extra high density
small Resources for small size screens.
normal Resources for normal size screens. (This is the baseline size.)
large Resources for large size screens.
xlarge Resources for extra large size screens.
And make sure "adjust view bounds"=true in your xml
follow this for more deatils
As far as I can tell (and correct me if I'm wrong), if you want to have graphical buttons that look good (with nice anti-aliasing) on multiple sized devices, you have to create different a set of different sized images and place the images inside a collection of different directories. I am looking to find a worked example showing exactly which set of directories to use and what the relative sizes need to be for those directories.
By the way, when I say ImageButtons, I mean containing an image instead of text - so 9patch images will not do the trick.
EDIT: One thing that particularly confuses me is the fact that I very often see examples (e.g. chuck258's answer) where people employ different screen densities... but if you make buttons with their width & height tuned for densities, then the fraction of the screen taken up with your button can vary in all sorts of uncontrolled ways, if you have a high-density-but-small-sized screen, then your buttons will be overly large.
EDIT: Further to my last edit, maybe I should be more specific about what I want... let us say that I want a square ImageButton that is approximately 10% (I'll accept a variation from 8% to 13%) of the width of the (portrait only) screen ... what size images would I make and what directories would they be in?
EDIT: I'm getting the message that if you have more screen real estate, then the standard thing to do, is to allow the icons to take up a smaller fraction of the screen. Presumably this is because allowing icons to become very large, makes them look rather toy-like, or childish. BUT the thing is, I'm making game apps for children! So this is exactly what I want.
First of all you need to understand the difference between screen density and screen size.
The screen size is the physical size, measured as the screen's diagonal. Android groups all actual screen sizes into four generalized sizes: small, normal, large, and extra large.
A phone might have a screen size of 4.9 inch which would be considered normal, both Nexus 7 (the old one from 2012 and the new one from 2013) have a screen size of 7" which is large, the Nexus 10 has a screen size of 10" and that's extra large.
The screen density on the other hand is the quantity of pixels within a physical area of the screen; usually referred to as dpi (dots per inch). For example, a "low" density screen has fewer pixels within a given physical area, compared to a "normal" or "high" density screen.
For simplicity, Android groups all actual screen densities into four generalized densities: low, medium, high, and extra high (plus the new xxhdpi).
An old Nexus 7 has the same screen size as a new Nexus 7 but the old one has a resolution of 1280x800 which is 216 dpi or hdpi while the new one has a resolution of 1920×1200 pixels which is 323 dpi or xhdpi (more pixels within the same physical area means higher pixel density in dpi).
An image in the drawable folder will have the same physical size on small, normal, large and x-large screens if the screens have the same screen density. Because the screens have different sizes the image will take up a different fraction of the screen. On small screens it will take up a larger part in percentage than on a large screen.
Nothing will change if the same image is in one of the screen size folders (drawable-small, drawable-normal, drawable-large, drawable-xlarge) but you can decide to put a larger version of the image in drawable-xlarge. In that case the image would be larger on a Nexus 10 than on a new Nexus 7 (both have xhdpi pixel density).
If the screens have a different pixel density that same image will look differently though. The image would be half the size on an xhdpi screen compared to an mdpi screen (because the xhdpi screen has approximately double the pixel density):
http://developer.android.com/images/screens_support/density-test-bad.png
In case of an icon you usually want it to have the same size on different screens. That's why e.g. menu icons for mdpi screens are 32x32 and those for xhdpi screens are 64x64 and both are in the appropriate drawable folder (drawable-mdpi and drawable-xhdpi):
http://developer.android.com/images/screens_support/density-test-good.png
Now when do you use the pixel density and when do you use the screen size drawable folders?
Pixel density folders are used if the image should have the same physical size on screens with different screen densities which is usually what you want. If you use the same image for an old and a new Nexus 7 it would have a different size even as the screens have the same physical size and that's not what you want. So using density dependent images is imperative.
Screen size folders are used if you want an image to have a different physical size on small, normal, large and x-large screens. If I have a grid navigation with 6 icons on the main screen and I don't want to make use of the extra screen real estate on larger screens (e.g. by adding more icons), then I would provide a small image for the small screen and a large image for the large screen.
You would still have to provide density dependent images on top of the screen size dependent images as explained before (example old Nexus 7 vs. new Nexus 7).
So in theory you would need 16 different resources for the same image (4 screen sizes in 4 screen densities or with the new xxhdpi density even 5 densities -> 20 resources).
Now of course no one wants to create that many resources especially if you have a lot of images.
One approach is to use the Dashboard as someone has suggested:
http://developer.android.com/about/dashboards/index.html#Screens
and pick the most commonly used combinations which are small/ldpi, normal/mdpi, normal/hdpi and normal/xhdpi (81% of all devices). That way you bring down the resources to just 4.
Another approach is to provide resources for either screen size or for screen density (again only 4 resources needed) and then do some scaling in code.
If you have screen density dependent resources then you would use e.g. this https://stackoverflow.com/a/5016350/534471 to scale the images down (never up).
If you have screen size dependent resources then you would use this http://developer.android.com/reference/android/util/DisplayMetrics.html
to scale the images down.
There's a nice example for all this here (including source code):
https://www.captechconsulting.com/blog/steven-byle/understanding-density-independence-android
Now for you specific problem you could use one generic image in the folder drawable. The size of that image should be so that it won't have to be up-scaled (because that would look ugly). You define the button in the layout like this:
<ImageButton
android:id="#+id/myButton"
android:src="#drawable/myDrawable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
/>
Together with this piece of code the button scales to 10% of the screen:
Display display = getWindowManager().getDefaultDisplay();
Point screenSize = new Point();
display.getRealSize(screenSize);
int size = Math.min(screenSize.x, screenSize.y);
int buttonSize = Math.round(size * 0.1f);
ImageButton button = (ImageButton) findViewById(R.id.myButton);
button.setMaxWidth(buttonSize);
button.setMaxHeight(buttonSize);
How large should the original image be?
A Nexus 10 has probably the highest screen resolution of all Android devices at the moment. The 1600 pixels will translate to 3200 density independent pixels on its xhdpi display. 10% of 3200 is 320. If you use a 320x320 image then you will get a good result on all existing devices.
There's a catch to this approach though.
320x320 is pretty large (possibly 24/32 bit color depth) and thus you might run into memory issues. If you provide the same resource in the density dependent drawable folders you can lower the memory footprint for hdpi, mdpi and ldpi devices:
drawable-xhdpi: 320x320
drawable-hdpi: 240x240
drawable-mdpi: 160x160
drawable-ldpi: 120x120
The screen size drawable folders could be used to further improve this (smaller screens need smaller images) but then you'll have to provide the 16 or 20 resources as mentioned before. In the end it's a trade-off between memory footprint / speed on one side and maintainability / time to create the resources / apk size on the other side.
You should at all time create images for all densities. Most images like icons should be fixed height in terms of dp. images of surfaces that aren't fixed height should be 9patch images which are stretchable
More on 9patch here: http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch
Usual practice for Android platform is to provide images only for different screen densities, not for screen sizes. If I use tablet I don't want to see big images, I want see more information. So it's better not to increase size of views, but provide different layout for bigger screens.
But if you have some specific reason to provide image 10% of screen width you can use 'drawable' folders with different qualifiers. You are interested in 'Available width', 'Screen size' and 'Screen pixel density' qualifiers.
For example provide this images:
drawable-sw320dp-mdpi - image 32px width
drawable-sw320dp-hdpi - image 48px width
drawable-sw320dp-xhdpi - image 64px width
drawable-sw400dp-mdpi - image 40px width
... provide images for all devices you want support
I don't know if I get your question right, but for the relative sizes of the Image, see: http://developer.android.com/design/style/devices-displays.html .
You can use a large enough Image for the biggest Screen you want to support. Then use scaleType="fitCenter" in your Image. Some downsides of this:
If the Image gets too small you get the same Issues than this Guy mentioned: http://www.pushing-pixels.org/2011/11/04/about-those-vector-icons.html
Of course it is never optimal to load a potential huge Image to scale it down and apply anti alias.
And yes: ScaleType.FIT_CENTER is the programmatical equivalent the fitCenter property. In general you can expect every Property in your XML has a getter and setter.
Go to your project-->Ctrl+n-->Android-->Android Icon Set-->Next-->enter name of icon-->next-->image-->browse-->select image from your PC-->None-->finish.
thats it it will automatically creates single image in 4 different sizes in 4 folders named
1.drawable-hdpi
2.drawable-mdpi
3.drawable-xhdpi
4.drawable-xxhdpi
so you can use this image in your application it will take that image based the device screen sizes.
You could do something like this:
package com.example.test;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.os.Bundle;
import android.view.Display;
import android.view.Menu;
import android.widget.ImageButton;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Get ImageButton from XML
ImageButton ib = (ImageButton) findViewById(R.id.imageButton);
//Get the screen size
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
//10% of the screen width
int width = (int) (size.x * 0.1);
//Get and scale the Bitmap (10% of screen width)
Bitmap bitmap = getImage(R.drawable.ic_launcher, width, width);
ib.setImageBitmap(bitmap);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public Bitmap getImage (int id, int width, int height) {
Bitmap bmp = BitmapFactory.decodeResource( getResources(), id );
Bitmap img = Bitmap.createScaledBitmap( bmp, width, height, true );
bmp.recycle();
return img;
}
}
And the ImageButton:
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageButton" />
This doesn't answer your question exactly. but if you're just looking for generic icons take a look at t IconicDroid library it helped me a lot. You'll be able to resize the icon as much as you want without looking quality and it also saves a lot space so the apk will be smaller. There is a demo of this library on the google Play.
Let's say you nedd imageButotn 10% of width for different Screens sizes it will be
32 for (320x480) mdpi
48 for(480x800|854) hdpi
64 for(640x1024 (galaxy tab 7")) large-hdpi
72 for(720x1280 (nexus 7)) large-tvdipi
72 for(720x1280 (xperia sp,etc) xhdpi
80 for(800x1280 (motorola xoom 10") xlarge-mdpi
108 for(1080x1920 (xperia z,etc) xxhdpi
so u make images at all this sizes and put them in the folders they should be.
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!
From my understanding of the Android support for multiple screens Support, layouts are scaled for screen density and size, whereas images are scaled for screen density.
This ensures that images will appear the same size on different density screens. To overcome possible scaling issues, it is recommended to provide different versions of the images with following the 3:4:6:8 scaling ratio between the four generalized densities.
However, if I have a screen that is simply to display a photo with some text underneath, and I want to take advantage of the extra screen size in some mobiles, and therefore display the photo at a larger size from the user's point of view than on the smaller screens, then what is the best way of doing this?
Also wrt displaying images, is it best to use wrap_content or dp – what is the advantage of one over the other ?
Thanks very much in advance
P
In answer to your first question:
You probably need to specify a different drawable resource for every image you're going to do. Here is a link to the android developer's site that specifies methods of doing that. http://developer.android.com/guide/practices/screens_support.html
Second:
If you specify the dp, you may cause some image distortion, however, if you use wrap_content, it may not be big enough. I would suggest for you to use wrap_content with different drawables for each screen density.
EDIT:
To find the actual size:
Display display = getWindowManager().getDefaultDisplay(); int width = display.getWidth(); int height = display.getHeight();
You're going to have to calculate it though based on the screen density.
And then just use mm or inches