So I get the whole Android pixel independency thing.
I'm creating a SplashScreen that is using a 9patch that will stretch its edges to account for all screensizes.
I also use a differenlty sized 9patch image in ldpi mpdi hdpi xhdpi for each splash screen as well.
That way the logo (the non stretched area of the 9patch) will be the correct size.
I know mdpi is 1.0 and hdpi x1.5 in relative size and xhdpi is x2, but when I'm creating that first mdpi image how do I know how many pixels wide/high it should be?
Hope that makes sense.
Really there's no one answer. Firstly though, I wouldn't start at mdpi and scale up -- It's best to start at the highest quality that you can. Vector, if it fits the design, or a high resolution image (even larger than the largest screen size you currently plan to support). Then, from there, just downsize for the device that you plan to test. For example, a typical HDPI resolution would be 480 x 800, so fit it appropriately there. An XHDPI resolution might be something like 1280 x 720. It's best to just leave a good amount of margin on the edges in case it's used on a device with a different aspect ratio, or something. But yeah, basically, design as large as you can, and then just export based on some average screen resolutions for the density bucket you're working on.
(...) when I'm creating that first mdpi image how do I know how many pixels
wide/high it should be?
Since mdpi is the baseline for all other density buckets, 1dp on an mdpi device will translate to exactly 1px. In other words, use an mdpi device to figure out the relative size on the screen and from there on apply the given scaling ratios to produce resources for the ldpi, hdpi and xhdpi buckets. Obviously you do not actually have to scale up that mdpi resource - all you need determine is the size for that screen density and then you can use whatever source file to produce images for all buckets.
The link xBroak has given, is actually the best source of information regarding your question. A quote from there to support above statements:
The density-independent pixel is equivalent to one physical pixel on a
160 dpi screen, which is the baseline density assumed by the system
for a "medium" density screen.
It may also come in handy to be aware of the simple d(i)p to px formula (also from that same link):
The conversion of dp units to screen pixels is simple: px = dp * (dpi
/ 160)
With this information, you can easily verify that 1dp on an mdpi device (with 160dpi screen) is equal to 1px. Just fill in 160dpi and you get px = dp * (160 / 160), which simplifies to px = dp * 1, and hence px = dp for 160dpi. QED. :)
These are your basic guidelines:
xlarge screens are at least 960dp x 720dp
large screens are at least 640dp x 480dp
normal screens are at least 470dp x 320dp
small screens are at least 426dp x 320dp
320dp: a typical phone screen (240x320 ldpi, 320x480 mdpi, 480x800 hdpi, etc).
480dp: a tweener tablet like the Streak (480x800 mdpi).
600dp: a 7” tablet (600x1024 mdpi).
720dp: a 10” tablet (720x1280 mdpi, 800x1280 mdpi, etc).
More info: http://developer.android.com/guide/practices/screens_support.html
Related
i have screen which is deisgned in XHDPI .
I have to convert all padding ,margin value of dp into LDPI,MDPI,HDPI,XXHDPI,XXXHDPI
Can any one please suggest me how i will calculate dp value for follwing screen suppose i have paddingTop in xhdpi is 56dp then what value we have give for ldpi,mdpi, xxhdpi and xxxhdpi
please suggest me.
Density-independent pixel (dp)
A virtual pixel unit that you should use when defining UI layout, to express layout dimensions or position in a density-independent way.
The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen, which is the baseline density assumed by the system for a "medium" density screen. At runtime, the system transparently handles any scaling of the dp units, as necessary, based on the actual density of the screen in use. The conversion of dp units to screen pixels is simple: px = dp * (dpi / 160). For example, on a 240 dpi screen, 1 dp equals 1.5 physical pixels. You should always use dp units when defining your application's UI, to ensure proper display of your UI on screens with different densities.
If you want to know what's 56dp in xhdpi, that's 56dp in ldpi, mdpi, hdpi, xxhdpi, xxxhdpi as well - as the definition says, it's density-independent pixels.
When you work with a design, you want to know one thing:
What's the baseline scale for the design?
Some quick answers: It's usually 1x, 2x or in rare cases 3x
Android defines the following densities:
ldpi (low) ~120dpi
mdpi (medium) ~160dpi
hdpi (high) ~240dpi
xhdpi (extra-high) ~320dpi
xxhdpi (extra-extra-high) ~480dpi
xxxhdpi (extra-extra-extra-high) ~640dpi
There are some rare cases in-between, like tvdpi, but in 99% of the cases you can just simply ignore those.
When designers say 1x, they usually refer to mdpi, 2x (or retina) refers to xhdpi and 3x design is done in xxhdpi.
Once you know the baseline, you know how to translate the pixel values from the design document to dip (density-independent pixel).
The formula is quite simple, but if you doubt yourself, feel free to try one of the online converter tools:
https://pixplicity.com/dp-px-converter
http://angrytools.com/android/pixelcalc/
The formula is as follows: dp = px / (dpi / 160) where dpi is the current screen density and px is the value in the base (1x) density.
Or the other way around.
Also, remember to read the Best Practices from the Android Developers page!
If you still end up using px in your dimensions file which are not recommended, please take a look at this answer to know how to create different values folder for different screens.
I'm struggling with a pretty trivial task in the Android "multiple-screen sizes" domain.
What I'm trying to achieve
A layout matching the screen width, with a nine-patch background which resizes (only horizontally, since there is always enough vertical space). Here is a dummy image:
My goal is, depending on the screen resolution, to display the image at the highest resolution possible, by using a set of different sizes, eg. 320x45, 480x67, 600x87, 720x101, without any down-scaling. I'm hoping for a non-programmatic solution.
An example with the above mentioned image sizes would be:
3.7" Nexus One (480 x 800) - the 480x67 image would look best.
4.7" Galaxy Nexus (720 x 1280) - the 720x101 image.
4.7" Nexus 4 (768 x 1280) - again the 720x101 image, stretching to the full 768 px width and becoming 768x101.
Issue
The whole Android resource allocation revolves around dps (density-independent pixels), when in fact I want to display an image based on the actual available pixels.
If I allocate the 480x67 image to res/drawable-mdpi and a 600x87 to res/drawable-hdpi, then image would display correctly on a 5.4" display of 480x800, i.e. mdpi display. However, a 4" 480x800 displays qualifies as hdpi and the system would appoint the 600x87 image, which won't fit the screen.
I tried the smallestWidth parameter as described in the online guide, but that yields strange results. For instance, a 3.7" 480 x 800 display (hdpi) uses my drawable-sw320dp image, although there is a drawable-sw480dp resource available too.
What is the best way to assign a stretchable, width-matching image with the best possible quality? Isn't there any non-programmatic solution?
Thanks in advance!
I believe that by combining density and screen size resource qualifiers you can achieve a close to optimal behavior.
Lets assume this kind of resource folders structure:
drawable-normal-hdpi - A normal size dictates minimum width of
320dp. hdpi dictates 1.5X dp to pixel multiplier. So the minimum px
width of the normal hdpi bucket is 480px. We put here a 480px wide
image.
drawable-normal-xhdpi - Again size dictates 320dp but this time
with 2X multiplier. So we use a 640px wide image.
drawable-xlarge-mdpi - Size means at least 720dp. mdpi multiplier
is 1X, so we use a 720px wide image.
Now lets look at some devices to see how they fall in with those buckets:
Nexus one - normal hdpi. Actual px width: 480px. The image fits
perfectly.
Galaxy nexus - normal xhdpi. We could fit a 720px image, so the
640px image we use isn't optimal - but it's very close.
Nexus 4 is just like the Gnex.
Nexus 10.1 (1280X800) - xlarge mdpi. We could fit 800px, our image
is 720px. Again not ideal but close enough.
Worst case scenario: image used could have 5-10% better quality.
Best case: perfect fit.
The main down side of this method is that you need to provide a lot of resources and folders to account for all the permutations of sizes and densities (even worse if you need to combine that with more qualifiers for locale, orientation and so on). However, as far as my Android understanding goes I don't think you can achieve something better than this without coding.
A remark regarding smallestWidth: Your example for the weird behavior is actually the expected behavior.
hdpi multiplier is 1.5 - So a 480px wide hdpi display is exactly 320dp wide. This makes the drawable-sw320dp the right choice, as documented. I'm not sure if you can combine the smallestWidth qualifier with the dpi qualifier. If it's possible you might get more accurate results than just size modifiers. But this would mean a lot more permutations for a 5% increase in image quality. Probably not worth it.
Actually, your method is not how it is supposed to be. I will suggest 2 ways for you, one is easy but doing programmatically, other one is using a custom view.
Method 1 - Programmatically
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int screenWidth = displaymetrics.widthPixels;
// this will determine "scale ratio" so using which image height and width won't matter
int imageOriginalHeight = 101; // your original image height
int imageOriginalWidth = 720; // your original image width
int imageScaleHeight = (screenWidth*imageOriginalHeight) / imageOriginalWidth;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(screenWidth, imageScaleHeight);
imageView.setLayoutParams(params);
imageView.setImageResource(R.drawable.file);
Method 2 - Custom View
You can use a custom view called ScaleImageView which is written by Maurycy Wojtowicz.
Class is defined like below:
This view will auto determine the width or height by determining if
the height or width is set(exact size or match_parent) and scale the
other dimension depending on the images dimension This view also
contains an ImageChangeListener which calls changed(boolean isEmpty)
once a change has been made to the ImageView
Here is how you are going to implement it.
Create a class named ScaleImageView.java and copy contents of the link above.
In your xml file, create a ScaleImageView, just same like ImageView (the example I am writing below is for filling screenwidth, and scaling height according to that so there will be no empty spaces on right/left)
<com.project.customview.ScaleImageView
android:id="#+id/scaleImageView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="#drawable/file" />
If you need to declare and set programmatically in your Activity, it is also the same as using ImageView:
imageView = (ScaleImageView)findViewById(R.id.scaleImageView);
imageView.setImageResource(R.drawable.file);
In android you have the option hdpi, mdpi, xdpi,etc..
folders for that , you have to create different images according your device resolution and put your images at there after confirming your device resolution and density category.
for the more reference why it'll happen you can see here
here i explain some chart may be helpful to you.
Low density Small screens QVGA 240x320 (120dpi):
drawable-small-ldpi (240x320)
drawable-small-land-ldpi (320x240)
Low density Normal screens WVGA400 240x400 (x432) (120dpi):
drawable-ldpi (240 x 400 )
drawable-land-ldpi (400 x 240 )
Medium density Normal screens HVGA 320x480 (160dpi):
drawable-mdpi (320 x 480 )
drawable-land-mdpi (480 x 320 )
Medium density Large screens HVGA 320x480 (160dpi):
drawable-large-mdpi (320 x 480 )
drawable-large-land-mdpi (480 x 320)
Galaxy Tab ( 240 dpi ):
drawable-large (600 x 1024)
drawable-large-land (1024 x 600)
High density Normal screens WVGA800 480x800 (x854) (240 dpi):
drawable-hdpi (480 x 800)
drawable-land-hdpi (800 x 480)
Xoom (medium density large but 1280x800 res) (160 dpi):
drawable-xlarge (800 x 1280)
drawable-xlarge-land (1280 x 800)
According to this guide's chapter px = dp * (dpi / 160) and to that layout specifications change from buckets(physical size in inches) to "dp" units so that:
320dp: a typical phone screen (240x320 ldpi, 320x480 mdpi, 480x800
hdpi, etc).
480dp: a tweener tablet like the Streak (480x800 mdpi).
600dp: a 7” tablet (600x1024 mdpi).
720dp: a 10” tablet (720x1280 mdpi, 800x1280 mdpi, etc).
Since "dp" values depend on "px" and "dpi" values so that: dp = px / (dpi / 160) - isn't it possible that a phone device with high resolution will take a layout from w600dp folder?
For instance: Samsung galaxy s3 dp = 1280 / (303 / 160) = 670; Samsung galaxy s2 dp = 800 / (217 / 160) = 592. So, galaxy s3 is going to take "tablet-oriented" template, right. Is it okay, especially if a tablet version contains more elements and overall interface ergonomics gonna suffer from the tablet layout in case of s3 ? Why don't just stick to display buckets ?
You're probably going to recommend using "sw" key but I just want make sure that those "dp" units actually relate to sizes so that tablet-oriented template won't be shown on phone devices.
So, would you mind sharing your practical knowledge on applying the new approach ?
Thanks
A dp or dip is a (screen) Density Independant Pixel. The confusing part about that is that is mentions pixel. It is actually a unit similar to a centimeter or inch.
Each device defines a dpi bucket for it's screen, for example mdpi which is 160dpi. That means that you find 160 pixel across one inch on the screen. It's not 100% accurate since physical screens are usually not exactly 160 dpi (or whatever value that is defined for the bucket). But it's a value that comes close.
That means that 160dp on a perfect 160dpi screen are actually 160 pixel. On a device with a perfect xhdpi (=320dpi) screen those 160dp would be 320 pixel. (px = 160dp * (320dpi / 160))
To work with dp don't think in pixel. Think in inch, milimeter or what unit you prefer. The recommended 48dp rythm for UI elements for example explains that
On average, 48dp translate to a physical size of about 9mm (with some variability)
To approximate that: 50dp = one finger wide.
That hopefully explains why a typical 320dp phone screen is always smaller than a 720dp tablet screen although the smaller screen can have more pixel than the larger. The dpi / pixel thing is already factored into dp.
How to do different layout for different screensizes? (i.e. phone vs table)
Use the screen size buckets (small, ..., xlarge) for the layout. They represent physical small to large screens. You don't need sw600dp etc unless you need to adjust very special cases.
The different dpi buckets should only concern you for images. E.g. high resolution images for high resolution screens of any size in the drawable-hdpi folder.
The S3 does not have a density of 160.
I have two android devices with the same screen resolutions (800x480) and dimensions.
The difference is that one screen is low density (120 dpi) and the other normal density (160 dpi).
I don't understand the reason by the same image of 200x200pixels is smaller in the screen with less density and if i write a rectangle of 200x200 pixels is the same on both screens.
Can anybody explain me the reason?
Thanks in advance
A 90 pixel image at ldpi becomes a 120 px a mdpi, a 180 at hdpi and a 240 ad xhdpi.
You can find more informations about it here (search "Screen pixel density") : Dev Android Ressources
Another good link about Density : Screen Support - Density
I've read 10 articles yet still cant find any relation between ldpi, mdpi, hdpi and the actual dimensions in pixels!? Can anybody give a straightforward answer please(if there is one!)
I'm basically trying to put together a splash screen that needs to work on multiple devices without stretching - but i'm struggling as everything I try is either squashed or stretched!?
Cheers
Paul
The ldpi, mdpi and hdpi refer to screen density, which means how much pixels can fit into a single inch.
the ratio in pixels between them is:
ldpi = 1:0.75
mdpi = 1:1
hdpi = 1:1.5
xhdpi = 1:2
xxhdpi = 1:3
xxxhdpi = 1:4
so lets take an image with about the size of 100X100:
for mdpi it should be 100X100
for ldpi it should be 75X75
for hdpi it should be 150X150
for xhdpi it should be 200X200
for xxhdpi it should be 300X300
for xxxhdpi it should be 400X400
this way, for screens with the same size but different DPI, all the images seem the same size on screen.
Also you have multiple screen size types small, normal, large, xlarge and each one of them can be ldpi, mdpi, hdpi, xhdpi, xxhdpi (Nexus 10) or xxxhdpi.
You can try to create a splash screen image that fit to each and every screen type
which gives you 4*5 = 20 different images (it seems to much for me).
For now only the Nexus 10 is at the xxhdpi category.
Install ImageMagick and use this shell script to generate your splash and icon files for multiple devices - iOS, Android, Bada and Windows Phone. You can use cygwin/gitbash if you are on Windows
I just did and I'm pretty happy with it :-)
The screen sizes are inside the script and are -
480x800 - screen-hdpi-portrait.png
320x200 - screen-ldpi-landscape.png
720x1280 - screen-xhdpi-portrait.png
320x480 - screen-mdpi-portrait.png
480x320 - screen-mdpi-landscape.png
200x320 - screen-ldpi-portrait.png
800x480 - screen-hdpi-landscape.png
The definitions are:
xlarge screens are at least 960dp x 720dp. large screens are at
least 640dp x 480dp. normal screens are at least 470dp x 320dp.
small screens are at least 426dp x 320dp. (Android does not currently
support screens smaller than this.)
Also, check out this blogpost from Dianne Hackborne:
http://android-developers.blogspot.com/2011/07/new-tools-for-managing-screen-sizes.html
Probably the easiest thing is to use an image view and set the scaletype to CENTER_CROP.
(Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the image will be equal to or larger than the corresponding dimension of the view).
Make sure that you use the src tag rather than setting the background.
<ImageView
android:id="#+id/home_video_layout"
android:src="#drawable/splash_image"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
/>
Updated:
Understanding Screen Densities and the “dp”
Resolution is the actual number of pixels available in the display, density is how many pixels appear within a constant area of the display, and size is the amount of physical space available for displaying your interface. These are interrelated: increase the resolution and density together, and size stays about the same. This is why the 320x480 screen on a G1 and 480x800 screen on a Droid are both the same screen size: the 480x800 screen has more pixels, but it is also higher density.
To remove the size/density calculations from the picture, the Android framework works wherever possible in terms of "dp" units, which are corrected for density. In medium-density ("mdpi") screens, which correspond to the original Android phones, physical pixels are identical to dp's; the devices’ dimensions are 320x480 in either scale. A more recent phone might have physical-pixel dimensions of 480x800 but be a high-density device. The conversion factor from hdpi to mdpi in this case is 1.5, so for a developer's purposes, the device is 320x533 in dp's.
I have found this online dip <--> pixels calculator very useful.
https://pixplicity.com/dp-px-converter/
I support previous answers but don't forget the power of Draw9Patch or using NinePatchDrawables
These refer to screen pixel density, not screen dimension. You need to look into screen size specifiers like small, medium, large, and xlarge instead if you really need to change behavior based on screen size in pixels.
The Android docs explain what densities and sizes match these identifiers.
Android devices can have different width-to-height ratios, while your image has a fixed one. If you do not want your image stretched, you will have to fill the blank spaces above and below or left and right.