Microsoft has always been quite strict on hardware specifications for Windows Phone devices.
This has both advantages as well as some drawbacks. For example, to developers this means that they don't have to worry as much about what features are available on devices and which ones aren't, something that is a lot more annoying to deal with on other platforms like Android.
On the other hand, strict specifications also limit the possibilities of hardware vendors to divert and the options of customers to choose between e.g. high-end and low-end devices.
One of the details of these specifications is screen resolutions. All Windows Phone 7.x devices on the market have the same resolution of WVGA, which is 480 by 800 pixels. Initially there was a planned additional resolution of 320 by 480 (HVGA) [1] to support lower end devices, but no such devices or even platform updates with support for this ever showed up. Practically, we faced a very homogenious environment in that context, with a single resolution to target. In Windows Phone 8 however, the supported screen resolutions are extended to some additional high-end options. In this part of the series, we will take a look at this in detail and see how it will affect developers.
New Screen Resolutions
In addition to the existing resolution of 480 by 800, two new options are added in Windows Phone 8, totaling in three available display resolutions that are listed below:
|
WVGA |
HD |
WXGA |
Resolution |
480x800 |
720x1280 |
768x1280 |
Aspect Ratio (1:1) |
15:9 |
16:9 |
15:9 |
Supported by |
Windows Phone 7.x/8.0 |
Windows Phone 8.0 |
Windows Phone 8.0 |
To get a better feeling of what we are talking about we can take a look at true to scale visual representations of these:
Isn't that impressive? Personally, I was aware of these values before and I had read them multiple times in dozens of places, but it was only until I've seen those scaled images that my reaction simply was "wow, that's a lot of additional pixels".
Now, one of the important details to realize is something that people usually have a natural understanding of, but that needs to be discussed a bit more: these values obviously don't translate into physical dimensions of devices. Let's take a look at another visual comparison, this time of the screen size of a Nokia Lumia 900 (Windows Phone 7.x) and a Nokia Lumia 920 (Windows Phone 8.0):
As you can see, despite the fact that the 920's resolution is much higher, the physical screen size is almost identical to the Lumia 900. By the rules of logic, if the physical size is about the same but the number of pixels is much higher, then the density of the pixels must be increased (they need to be packed together more tightly). This is exactly what is expressed by the last number in the images, which denotes the "pixels per inch" (ppi) [2]. The Lumia 900 has ~217 ppi, whereas the Lumia 920 has 332 ppi according to Nokia's data sheets (if you calculate it manually, the result is 335 or 336, depending on whether you use the width or height).
An interesting fact is that, depending on the viewing distance and the visual acuity [3] of course, the average human eye cannot differentiate individual pixels beyonds ~300 ppi. This means that displays with a ppi that high don't need to resort to techniques like anti-aliasing to smooth text and images anymore, and they have the potential to compete with printed content with regards to visual quality. This is a very important thing to keep in mind, because it heavily influences how we as developers are supposed to work:
The benefit of these higher resolutions is that we can improve the visual quality of whatever is displayed.
We do NOT want to cram more stuff into that additional screen real estate.
Creating mulitple versions of a user interface (or a single one that nicely supports multiple resolutions) often can be a time-consuming task that requires different layouts or heavy view logic to reflow the elements on the screen. The above strong postulate hence makes things much easier for us developers, as we really don't need to create those different layouts or care too much about those different resolutions. In fact, Windows Phone handles most of this for us nicely out of the box.
Develop for Multiple Resolutions
The first indication of how you are supposed to work with the new resolutions becomes apparent when you try to access the width and height values of the available phone content area, using code like this:
var resolution = string.Format("{0}x{1}",
Application.Current.Host.Content.ActualWidth,
Application.Current.Host.Content.ActualHeight);
For a WVGA device, this results in the expected value of "480x800". Surprisingly however, when you run the same code on a WXGA device, the returned value still is "480x800". With an HD device, we have a slight change, but the result still is highly unexpected: "480x853". Huh? When you take a look at the documentation of these properties [4][5] you can see that it talks about "logical pixels":
"The height, in logical pixels, of the Windows Phone application content area."
So as a developer, you always work with the same WVGA "logical" resolution to layout your application. The small difference with the HD resolution is a result of the different aspect ratio (16:9 as opposed to 15:9 for the other formats) and we'll return to that in a minute. To get an idea of the real physical resolution your application runs on, you have to take a look at the third interesting property on the "Content" class: "ScaleFactor" [6] which is a property new to Windows Phone 8.0:
var resolution = string.Format("{0}x{1} (Scale factor: {2}%)",
Application.Current.Host.Content.ActualWidth,
Application.Current.Host.Content.ActualHeight,
Application.Current.Host.Content.ScaleFactor);
When you run the code, you can see that this scale factor returns different values depending on the physical resolution of the device. The following is an overview of the current characteristics of all these properties:
|
WVGA |
HD |
WXGA |
ActualWidth |
480 |
480 |
480 |
ActualHeight |
800 |
853 |
800 |
ScaleFactor (%) |
100 |
150 |
160 |
Resulting Size (Width/Height x Scale) |
480x800 |
720x1280 |
768x1280 |
What happens behind the scenes is that the content you as developer created for the logical resolution is scaled up to the real physical size of the device screen at runtime. The fact that the XAML layout system is based on vector graphics makes it possible to do this for text and other content without any loss in quality (limitations see below). The result is that users with those high-end devices immediately benefit of the much better visual quality.
The only potential problems are caused by the different logical height of the HD resolution. As long as you stick to relative sizing (for example using grids with star and auto sizing) there shouldn't be a lot of problems. However, when you start working with pixel-perfect layouts (or bitmaps, for that matter), things might be a little off on these devices. For example, when you place a fixed sized element of 480x800 as background of your app it works equally well on both WVGA and WXGA devices but it is padded by 80 pixels when it runs on an HD device – depending on the value of the VerticalAlignment for this element this can be padding at both the top and bottom or either side.
It's possible to indicate the supported resolutions in the WMAppManifest.xml for your application. If your app really is not capable of handling the HD resolution very well, you can remove it there:
However, this of course should be an exception or a temporary setting until you fix the issues. Your primary goal always should be to ensure your application works well on all of the available devices so you don't block out potential users (for example, the upcoming Samsung Ativ S has an HD screen).
How to Handle Bitmaps
The above mentioned upscaling works well for all kinds of vector graphics. However, in some cases you will use bitmap assets in your applications, for example as background images or icons and similar things. These images cannot be scaled very well by their nature, and something that looks great at a resolution of 480x800 might be distorted or not optimal at 720x1280 or 768x1280. There are some solutions to this problem.
One idea would be to create individual versions of your bitmap resources for each one of the potential resolutions. That means that you would package an image in three different sizes with your application, and then choose the most suitable based on the above described ScaleFactor property. The drawback is that this will increase your application package size significantly if you have a lot of images, and it requires you to distinguish between different resources in all places of your app.
Another solution uses a simpler approach: scaling down bitmaps works a lot better than scaling them up, because reducing existing information is a much simpler task than creating missing information out of nowhere. So instead of working with bitmaps that are designed to be used with a physical resolution of 480x800, you can create and package your bitmaps to target a physical resolution of 768x1280. If your app runs on a WVGA device the images will be scaled down, which results in a better experience than the other way round. The drawback is that this does not eliminate the problem completely. While this is a nice solution for things like sprites, icons and thumbnails, you still would have to provide different versions in those situations that depend on the screen aspect ratio, for example for background images.
Other Things to Know
There are some other interesting details that I list as a small Q&A section here:
- Is it possible to work with the actual, physical pixels directly? No. Whenever you layout elements on the screen e.g. in your XAML, you are always working with the logical pixels, never with the physical dimensions.
- The automated scaling sounds great, but I'm worried how well this works for small sizes (rounding issues)? The scaling logic usually rounds up values that are small. However, it also has some optimized code paths to handle certain situations in a specific way to avoid weird results. Testing your applications with different resolutions (also possible in the emulator) should be reassuring :).
- Isn't using high-res resolution assets on WVGA devices a waste of memory? It's true that images that are high-res and simply scaled down for display still take up the same amount of memory as when they're displayed in full size. However, you can make use of the new DecodePixelWidth and DecodePixelHeight features [7] to get more control over this and have images only occupy as much memory as required to display them, for example:
var bmp = new BitmapImage();
// no matter the actual size,
// this bitmap is decoded to 480 pixels width (aspect ratio preserved)
// and only takes up the memory needed for this size
bmp.DecodePixelWidth = 480;
bmp.UriSource = new Uri(@"Assets\Demo.png", UriKind.Relative);
ImageControl.Source = bmp;
If you want to learn more on the topic, a nice start is the talk "XAML Application Development" by Shawn Oster from Build 2012 [8] (the details on screen resolutions start around 8 minutes into the video).
Conclusion
The new screen resolutions that are available in Windows Phone 8 try to improve the user experience significantly without putting too much burden on the developer. You don't have to re-think your application completely or even create completely different versions of it, yet still the user can benefit from much improved visual quality immediately. Only for certain content like bitmaps do you need to take those new options into consideration, and you have to be a bit careful to handle the different aspect ratio of HD devices nicely. Other than that, multiple screen resolutions support is another one of these "for free" features that we see in Windows Phone 8.