Cracking Android Screen Sizes

We will explore Android’s different screen sizes and have a clear understanding of various terminologies

Hayk Mkrtchyan
Better Programming

--

Table of ContentsIntroduction
Pixel and Screen size
Pixels Per Inch (PPI) and how it is calculated
Different Densities in Android
How to calculate device density
Working with sizes
Wrap Up

Introduction

In Android, there are many display-related qualifiers, which sometimes confuse developers. What are DPs? How are they different from DIP? What are the various densities? How do all the calculations happen? Is it possible to get screen width and height in inches? In this article, I will answer all of these questions.

P.S. This article is not about how to support multiple screen sizes.

Pixel and Screen Size

I guess everyone knows what are pixels. If you will capture your monitor and zoom in, you can see small squares with an RGB color in them. All these small squares are pixels. Pixel is also stand for picture element (pix = picture, el = element). They are the basic building blocks of a digital image or display. If the monitor resolution is 1280px width and 720px height then overall that monitor has 921 600 pixels. It also represents the pixel density. With higher density, the quality of the image will become better. If the monitor resolution is 3840x2160, overall it has 8 294 400 pixels.

Now, what is the screen size? It is the distance between opposite corners. It’s also called diagonal. If the distance is 6.5 inches then the screen size is 6.5.

So how these screen size and pixels are connected? Let’s take a display, which resolution is 1080x1920 (width x height) and screen size is 5.5 inches. Overall there will be 1080 * 1920 = 2 073 600 pixels on the screen.

Now a question for you: Suppose we have 2 devices, they have the same resolution 1080x1920, but the first device screen size is 7.0 inches and the other one 5.5 inches. In which device the screen quality will be better? The answer we need to find in the next section.

Pixels per inch (PPI) and how it is calculated

Before starting, let’s make clear one thing. In Android PPI and DPI (dots-per-inch) are the same thing. In real life they are different, but Android team chose to use DPI rather than PPI.

Sometimes, if you will have a look at device specifications, in the display section you may see PPI value. It stands for Pixels-Per-Inch, which represents pixels count in one inch of the device.

How is PPI calculated? To calculate PPI, we need screen resolution WxH and the screen size. The formula is:

Formula to calculate screen PPI

Let’s take the values from the section above. If our screen resolution is 1080x1920 and screen size is 7.0 inches, then PPI will be:

1080 x 1080 = 1 166 400
1920 x 1920 = 3 686 400
1 166 400 + 3 686 400 = 4 852 800
sqrt(4 852 800) = ~2203
2203 / 7.0 = ~315

So our PPI value for the 7 inches screen is approximately 315. Let’s do the same operation for another screen with the same resolution but 5.5 inches in size. In this case, PPI will be approximate ~401.

The screen quality is directly proportional to pixels count in 1 inch (PPI). If the PPI value is high, that device screen quality will be better.

Now let’s answer that question from the previous section. Which device screen quality will be better? Of course, 5.5 inches screen, because in 1 inch it has more pixels.

Different Densities in Android

From now, I will use DPI instead of PPI, because those are the same thing. Take a bit of special care here to not get confused later.

* In Android, when we create the UI, mostly we use DP as the size specifier for the views. DP (Density-independent pixels) is the same as DIP, don’t get confused. The only reason is that DP is more consistent with SP (Scale-independent pixels).

* SP (Scale-independent pixels) is the same as DP, with an additional scaling factor that is based on the font size which the user selects in the device’s system settings. SP should be used only as a unit for text. Avoid using SP as a unit for non-text components.

*Density is the same as DPI, it shows the pixels count in 1 inch area. In Android, DPI is just a measurement unit, which represents the density. E.g. for the device with a resolution 1080x1920 and 5.5 inches size we can say that device screen density is ~401.

I hope the terminology is clear. No? Just read it again more carefully))

Density, DPI and PPI are interconnected. Those are the same thing.

So what means density-independent? It means, that our view size will be independent of the screen density. You know, if we will specify our view size in pixels, it will change its size regarding density. Assume we have an ImageView which width and height are 200x200px. Now, if the device density will be 100 dpi, this ImageView will take 2 inches width and height on the screen. But if the device density will be 400 dpi, it will take 0.5 inches instead. I hope the terminology is clear. If you’re confused, read about PPI/DPI one more time.

So how it can be independent of density? To answer this, let me introduce the different density buckets, which exist in Android:

ldpi - low density bucket (~120dpi, 0.75x).
mdpi - medium density bucket (~160dpi, 1x)
hdpi - high density bucket (~240dpi, 1.5x)
xhdpi - extra high density bucket (~320dpi, 2x)
xxhdpi - extra-extra high density bucket (~480dpi, 3x)
xxxhdpi - extra-extra-extra high density bucket (~640dpi, 4x)

The ldpi bucket is not very common anymore.

As you see, Android has 6 density buckets. Of course, there is also nodpi (resources for all densities) and tvdpi (resources intended for TVs) buckets, but we will not cover them in this article. In screens with 160 dpi, 1dp is roughly equal to 1px. That’s why it’s called medium density. Also, it’s called in some places baseline density.

How to calculate device density

Let’s take the device from our examples, which density was ~315 dpi. If we’ll have a look at the densities table, we see that 315 dpi is in the middle of hdpi and xhdpi. Now to which density bucket our device belongs? Maybe hdpi? Or maybe xhdpi? Well, it can be either hdpi or xhdpi, we can’t expect. Manufacturers have some flexibility in picking the density. But usually, the device belongs to its nearest bucket. This means, the device which is 315 dpi, will be xhdpi and the device which is 401 dpi, will be xxhdpi.

Device density is 401 dpi
Device density is 315 dpi

When we specify our view size in dp, our view gets scaled regarding screen density. But how does Android know how much it has to scale the view? As we mentioned above, in 160 dpi screens 1dp is equal to 1px.

Let’s take the device whose density is 401 dpi. To get the scale factor we have to divide 401 to 160. The result determines how much the view will be scaled on this device. The answer is 2.51.

We can also determine how many pixels it is. Let’s take a simple view with the size 50x50dp. In our device, Android will multiply 50 with the scale factor to get view size in pixels for the current device. We’ll get 126px.

For the other device, which density is ~315 dpi, the scale factor will be ~1.97. So the same view with 50dp size, in this device will be 99 pixels. That’s why dp is density-independent. Each screen has its own scale factor which determines how many pixels will take the view on the screen.

Working with sizes

At this point, we already know many things about dp, px, screen size, and densities. Now it’s time for coding :)

We will cover some subtopics here:

  • How to get display real width and height?
  • How to determine device density and its scale factor?
  • Can we get display width and height in inches?
  • Find device screen size.

How to get display real width and height?

We can get the display’s real width and height in pixels using WindowManager class.

fun WindowManager.currentDeviceRealSize(): Pair<Int, Int> {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
return Pair(
maximumWindowMetrics.bounds.width(),
maximumWindowMetrics.bounds.height())
} else {
val size = Point()
defaultDisplay.getRealSize(size)
Pair(size.x, size.y)
}
}
val (width, height) = windowManager.currentDeviceRealSize()

In the above program, we have 1 extension function, which returns a Pair of Int. The Pair represents display width and height. Starting from Android 11 (API 30) defaultDisplay.getRealSize() function is deprecated.

How to determine device density and its scale factor?

How to determine the device density and its scale factor? Can we somehow determine what’s the device dpi?

Unfortunately, there’s no guarantee we can always get the correct values. There is one class which is called DisplayMetrics. It includes information about our display characteristics. We can retrieve DisplayMetrics instance using:

val displayMetrics = resources.displayMetrics

DisplayMetrics has some variables:

displayMetrics.density //The scale factor of the density
displayMetrics.densityDpi // The density of the screen

Sad news: These values don’t return the correct information about the scale factor and density. But instead, there are 2 variables, which usually return more accurate values.

displayMetrics.xdpi // The pixels count in inch for screen width
displayMetrics.ydpi // The pixels count in inch for screen height

The “xdpi” represents the pixels per inch of the screen in the X dimension. The “ydpi” is the same but for the Y dimension. Even in this case, we don’t have a 100% guarantee, that we’ll get the correct values. But in my practice I give advantage to these values. In most cases “xdpi/ydpi” return the same value, so it’s up to you which one to use.

Can we get display width and height in inches?

If we are lucky and got the correct values, we can easily count display width and height in inches.

val (width, height) = windowManager.currentDeviceRealSize()
val displayMetrics = resources.displayMetrics
val widthInInches = width / displayMetrics.xdpi
val heightInInches = height / displayMetrics.ydpi

We just have to divide our width in pixels by the pixels count per inch. For the width we use xdpi and for the height ydpi, because in the coordinates system x axis is the width and the y axis is the height.

Find device screen size

Well, it’s easy to calculate as we already have screen width and height in inches. Using the Pythagorean theorem we can easily determine our screen size.

The program will look like this:

val (width, height) = windowManager.currentDeviceRealSize()
val widthInInches: Double = (width / resources.displayMetrics.xdpi).toDouble()
val heightInInches: Double = (height / resources.displayMetrics.ydpi).toDouble()

val widthAndHeightSum = widthInInches.pow(2) + heightInInches.pow(2)
val screenSize = sqrt(widthAndHeightSum)

We can also use the Math class hypot() function which will internally do this calculation for us.

hypot() - Computes sqrt(x^2 + y^2) without intermediate overflow or underflow.

val (width, height) = windowManager.currentDeviceRealSize()
val widthInInches: Double = (width / resources.displayMetrics.xdpi).toDouble()
val heightInInches: Double = (height / resources.displayMetrics.ydpi).toDouble()

val screenSize = hypot(widthInInches, heightInInches)

In both cases, our program works fine. My device screen size is 6.3. The output I’ve got is:

Output

Wrap Up

In this article, we covered most of the things which confuse Android developers. Now you have a clear understanding of the pixels and the PPI, different density buckets and their specifiers, what is dp, and how it is independent of the density. You know about all the formulas and you can make your own calculations to get screen density.

In the end, we even wrote a program and performed different calculations, so you will have a clear understanding. From now you can dive deeper and explore more. Thank you for your provided time.

You can find the above source code in this gist.

--

--