What is the difference between px, dip, dp, and sp?
From the Android Developer Documentation:
px
Pixels - corresponds to actual pixels on the screen.in
Inches - based on the physical size of the screen.
1 Inch OR 2.54 centimetersmm
> Millimeters - based on the physical size of the screen.pt
> Points - 1/72 of an inch based on the physical size of the screen.dp or dip
> Density-independent Pixels - an abstract unit that is based on the physical density of the screen. These units are relative to a 160
dpi screen, so one dp is one pixel on a 160 dpi screen. The ratio of dp-to-pixel will change with the screen density, but not necessarily in direct proportion. Note: The compiler accepts both "dip" and "dp", though "dp" is more consistent with "sp".sp
> Scaleable Pixels OR scale-independent pixels - this is like the dp unit, but it is also scaled by the user's font size preference. It is recommended you
use this unit when specifying font sizes, so they will be adjusted
for both the screen density and the user's preference. Note, the Android documentation is inconsistent on whatsp
actually stands for, one doc says "scale-independent pixels", the other says "scaleable pixels".
From Understanding Density Independence In Android:
Density Bucket | Screen Density | Physical Size | Pixel Size |
---|---|---|---|
ldpi | 120 dpi | 0.5 x 0.5 in | 0.5 in * 120 dpi = 60x60 px |
mdpi | 160 dpi | 0.5 x 0.5 in | 0.5 in * 160 dpi = 80x80 px |
hdpi | 240 dpi | 0.5 x 0.5 in | 0.5 in * 240 dpi = 120x120 px |
xhdpi | 320 dpi | 0.5 x 0.5 in | 0.5 in * 320 dpi = 160x160 px |
xxhdpi | 480 dpi | 0.5 x 0.5 in | 0.5 in * 480 dpi = 240x240 px |
xxxhdpi | 640 dpi | 0.5 x 0.5 in | 0.5 in * 640 dpi = 320x320 px |
Is dp based on the physical size of the screen? (dp =1/160 of an inch)
A measurement unit like mm
or in
would be way less confusing since dp
measures the same real world observed length. It would be misleading on the other hand since dp
is not an absolutely defined unit.
The use of screen density buckets means that dp
is a bit fuzzy - but it will stay within reasonable (+/-20% ?) accuracy. Real world displays are usually not exactly e.g. 160dpi they can be 173.4 dpi and still be classified as 160dpi. The math carried out to convert from dp
to pixels on the screen is done based on these buckets and that means that the accuracy of dp
depends on how accurately your device screen meets it's classification.
But to clear your doubt: 160dp is always 1 (fuzzy) inch regardless of what device you hold in your hand. Easier to think of: 50dp = 1 (small) finger wide.
px Pixels
on the other hand are actual pixels. A full HD display has 1920x1080 of them but that unit says nothing about the screen size or how big such a pixel will appear to the user. dp
or dip
is a different unit and should have never been called "pixel" in my opinion.
Android - How does dp occupy different space in devices with different sizes?
Android defines a baseline dpi of 160 which is used as the reference to compute sizes for all screen densities:
pixel_size * (device_dpi / baseline_dpi) = result in "dp" units
>> or the other way around
dp_size / (device_dpi / baseline_dpi) = result in "pixel" units
Therefore, 1 pixel in a 240dpi device is equivalent to 1.5dp units:
1 * (240 / 160) = 1.5
and the other way around, 1.5dp units in a 240dpi device is equivalent to 1 pixel
1.5 / (240 / 160) = 1
The important fact to know is that 160 is the baseline used as the reference for all DPIs.
So, as dp units increase/decrease, the required pixels area to draw something translates into keeping the same size scale regardless of the device screen.
More information in the official documentation.
To be more clear:
The display size is not related to "dp units". The display size is just how big the display canvas is. The screen DPI defines how many dots fit in 1 square inch. And a "dp unit" is an abstract unit that, depending on the device's DPI, is scaled (up or down) to give "uniform dimensions" on any screen size, by using 160 as the baseline reference.
Is dp (Density-independent Pixels) a Physical Size?
Good Question!.
When they say physical size, they mean the physical number of pixels.
Since a high resolution screen has more pixels per inch then a low resolution screen. The physical number of pixels per dp will be less on the lower resolution screen.
That being said, most phone screens do not fit in perfectly into any bucket. What happens then is that android fits them into the closest bucket which can cause the number of pixel per dp to stray from the bucket amount.
Why use unpredictable dips in Android instead of predictable pts?
The reason why you should use dip (Density Indepentdent Pixel) is that this way your application will support multiple screen sizes. This means that if you set a value to 100dip, it would be translated into 75px on a low density screen (ldpi), 100px on a medium density screen (mdpi), 150px on a high density screen (hdpi) and 200px on a extra high density screen (xhdpi) but the layout will look the same on each screen (but scaled to the screen density).
The only reason to use pt is if you actually need the exact size and don't care about the screen density (I can't see when that would be the case).
You should read through this article to better understand why dp/dip is the way to go:
Supporting Multiple Screens
Also this similar question has a good explenation of the difference between the different units:
Difference of px, dp, dip and sp in android
When should I use sp, dp, px, in and mm? (Android)
Use dp (dip, device independent pixels). These are like pixels, except they treat every device, regardless of its actual pixel density, as if it had a pixel density of, I think 160dpi.
When you are specifying the size of text, use sp. It is to points (the standard way of specifying font size) what dp is to pixels.
Do not ever, ever use px (pixels). Same for pt (points).
If you are writing an application that is a ruler, you have a good reason for using mm and in. Not otherwise.
Better yet, use match_parent and wrap_content!
Why Lint shows warning when using in (inch) or mm (millimeter) units as dimension?
To be able to give a good answer to your question I first have to give an explanation on how DPI works in Android, so this answer is a bit long.
TL;DR: The documentation is correct, however the warning from Lint is also correct. That is there are some (buggy?) devices where mm
, in
and pt
doesn't work correctly.
DPI in Android
In Android there are two different kinds of density measures that can be accessed from the DisplayMetrics class:
- densityDpi - The screen density expressed as dots-per-inch. This value is always set to one of the generalized density buckets available in Android (e.g. Medium/160, High/240, Extra High/320).
- xdpi / ydpi - The exact physical pixels per inch of the screen in the X/Y dimension. It is not uncommon that this value is slightly different than densityDpi depending on what screen size and resolution the device have.
The dp
unit is calculated based on the densityDpi metric while the mm
, in
and pt
units are all calculated based on xdpi/ydpi instead.
Reported values
It is possible to divide devices into four different categories depending on what values they report for densityDpi and xdpi / ydpi:
- densityDpi is almost the same, or the same as xdpi / ydpi.
- densityDpi is noticeably smaller than xdpi / ydpi
- densityDpi is noticeably larger than xdpi / ydpi
- the xdpi / ydpi values are completely wrong.
Category 1 (densityDpi is the same as xdpi / ydpi)
Example devices: Samsung Galaxy Trend, Nexus 4, Nexus 7.
For these devices there it doesn't really matter if you use in
, mm
, or dp
. If you draw a square with sides 1 in
and one with 160 dp
they will be the same and both will be about 1 inch on the actual screen.
Category 2 & 3 (densityDpi is different than xdpi / ydpi)
Category 2 example devices: HTC One S, Sony Xperia V, Sony Xperia Z Ultra.
Category 3 example devices: Samsung Galaxy S4, Sony Xperia Z1, Nexus 5.
For these devices the densityDpi and xdpi / ydpi differs because the densityDpi must be set to one of the available density buckets. So the true physical dpi is rounded to match the nearest bucket and this is what is reported as densityDPI value. This is illustrated by Figure 1 in the Supporting Multiple Screens document.
This means that if you draw a square with side 1 in
and one with 160 dp
they will have slightly different size. For category 2 devices the 160 dp
square will be slightly smaller and for category 3 devices it will instead by slightly larger. If you take out a ruler and physically measure the squares on the screen of the phone you will see that the 1 in
square is 1 inch while the 160 dp
square is a bit smaller or bigger depending on category.
This is a natural consequence of the density buckets system in Android, but unless you have a deeper understanding of how this works it may be a bit surprising that things drawn with a fixed dp measure may look different on different phones.
Category 4 (incorrect xdpi / ydpi values)
Example devices: Samsung Galaxy Mini, Samsung Galaxy S3 Mini.
These devices are more problematic, they have a good value for densityDpi (their true dpi rounded to the nearest bucket), but they report bogus values for xdpi / ydpi.
For example Samsung Galaxy S3 Mini reports an xdpi of 160 and densityDpi of 240. The screen 480 px wide so if 160 dpi was correct this would mean a screen width of 3 inch, but in reality the screen with is 2.05 inch. Based on these numbers the actual xdpi value that the phone should be reporting is 234.
Another example is the Samsung Galaxy Mini which also reports an xdpi of 160, but has densityDpi set to 120. That screen is 240 px wide so that would give a physical width of 1.5 inch, but in reality the screen is 1.9 inch (actual xdpi of 126).
So on these types of devices it is not possible to trust the in, mm, pt units since they will result in things being way too small or way too big.
Examples
Category 1-3
This is three screenshots of a test app I've made taken on devices from category 1, 2 and 3. The green square is drawn to be 1 inch big based on using the xdpi and ydpi values while the red square is drawn to be 1 inch big using dp (160 dp).
When physically measuring the result with a ruler the green square was inch big in all these examples while the red square size differed somewhat as it's visible on the screenshots.
Category 4
This is a screenshot from a category 4 device. The green and red squares are the same as in the previous example, but here I have also added two more squares, a yellow square that is 1 in
and a blue square that is 72 pt
. As visible on the screenshot all squares except the red square are of equal size.
When physically measuring the result with a ruler the red square is about one inch big while the rest of the squares are only about 0.67 inch big.
The answer to the question
The warning from Lint refers to category 4 type devices that return incorrect values for xdpi and ydpi. Since xdpi / ydpi can not be trusted on these devices the units (mm
, in
, pt
) that depend on them can not be trusted either.
Is documentation wrong?
No the documentation is correct, these units are based on the physical size of the screen. However some problematic devices report wrong values for the physical size of the screen (xdpi / ydpi) to Android and then these units will be wrong as well.
And why Lint doesn't warn when using pt?
The Lint developers probably just forgot about pt
, it is just as problematic as in
and mm
.
The reason Lint recommends using dp
instead is because this is a unit that is used extremely frequently in Android so if any device had broken dp
units pretty much all applications would look horrible and it would be fixed before the device was ever released to market.
Related Topics
How to Edit the Text Files in Assets Folder in Android
Sqlitedatabase Close() Function Causing Nullpointerexception When Multiple Threads
Textview with Background Color and Line Spacing
How to Filter Listview Using Getfilter() in Baseadapter
Android Fingerprint API for Time Attendance App
Supportmapfragment.Getmap() Returns Null
Android: How to Return Async JSONobject from Method Using Volley
How to Remove Child Nodes in Firebase Android
Web App on Android Browser Width Issue
How to Get Raw Preview Data from Camera Object at Least 15 Frames Per Second in Android
Java.Lang.Nosuchmethoderror: No Static Method Setonapplywindowinsetslistener
Get Font Scaling Factor to Calculate the Fontsize
Disable Android Browser's Input Overlays
How to Handle Asynctask Onpostexecute When Paused to Avoid Illegalstateexception
Flag_Activity_New_Task Clarification Needed
Air 3 Native Extensions for Android - Can I/How to Include 3Rd Party Libraries
Stop All Toast Messages When Going to Another Screen in Android