Handling different resolutions

Cascades includes several features that can help you adapt your UIs to different screen resolutions. You can use different layout types to arrange your UI controls dynamically, or you can adjust the spacing between your controls to save space on smaller screens. You can even create separate sets of assets that are designed for different screen resolutions and let Cascades select the best set of assets when you run your app.

To let your apps work on the various devices that run BlackBerry 10, consider using the following approaches in your app.

Relative layouts

There are several types of layouts that you can use to position your UI controls, and each layout arranges controls in a different way. For example, a stack layout positions controls next to each other, either vertically or horizontally. An absolute layout places controls in exact positions that you specify (in pixels). To learn more about the layouts that are available, see Layouts.

Where possible, you should try to use a relative layout ( StackLayout and DockLayout), instead of an absolute layout ( AbsoluteLayout). As the name suggests, a relative layout arranges controls relative to each other and the boundaries of the container. If you use a relative layout and the screen size or resolution changes, your controls still maintain their relative positions. If you use an absolute layout and specify the positions of your controls yourself, you might find that the controls aren't in the right places when your app is viewed in a different resolution.

For example, consider the layout that's shown in the image on the right. This layout is designed for a screen resolution of 768 x 1280 and includes three Button controls in various positions.

There are several ways that you could achieve this layout. You could use an AbsoluteLayout and specify the pixel positions of each button. In this approach, you need to calculate the correct pixel positions for each button.

You could also use a DockLayout and use alignment properties to position each button relative to the edges of the screen. A DockLayout supports alignments such as left, right, and center, and you can use combinations of horizontal and vertical alignments to position your controls.

Screen showing a layout that you can create using either a dock layout or absolute layout.

Here's how to use an AbsoluteLayout to create this layout in QML:

import bb.cascades 1.0

Page {
    Container {
        background: Color.create(0.86, 0.86, 0.9)
        layout: AbsoluteLayout {}
        
        Button {
            layoutProperties: AbsoluteLayoutProperties {
                positionX: 412
                positionY: 550
            }
            text: "Right button"
        }
        
        Button {
            layoutProperties: AbsoluteLayoutProperties {
                positionX: 210
                positionY: 0
            }
            text: "Top button"
        }
        Button {
            layoutProperties: AbsoluteLayoutProperties {
                positionX: 210
                positionY: 1177
            }
            text: "Bottom button"
        }
    }
}

Alternatively, here's how to use a DockLayout to create the same layout:

import bb.cascades 1.0

Page {
    Container {
        background: Color.create(0.86, 0.86, 0.9)
        layout: DockLayout {}
            
        Button {
            horizontalAlignment: HorizontalAlignment.Right
            verticalAlignment: VerticalAlignment.Center
            text: "Right button"
        }
        
        Button {
            horizontalAlignment: HorizontalAlignment.Center
            text: "Top button"
        }
        Button {
            horizontalAlignment: HorizontalAlignment.Center
            verticalAlignment: VerticalAlignment.Bottom
            text: "Bottom button"
        }
    }
}

Now, consider what this layout looks like on a screen with a resolution of 720 x 720. The first image uses the AbsoluteLayout version, and the second image uses the DockLayout version:

 
Diagram showing an incorrect version of the layout.
Diagram showing a correct version of the layout.
 

In the AbsoluteLayout version, the right button is cut off and the bottom button isn't even displayed. Because the buttons in this version were positioned using pixel coordinates, the layout isn't adjusted automatically when the resolution changes.

In the DockLayout version, the buttons maintain their positions relative to the edges of the screen. Using a relative layout is clearly better in this situation, and it's often the case that relative layouts preserve the appearance of your UIs better than absolute layouts do.

Margins and space quotas

Margins determine how much space appears between adjacent UI controls in a layout. Using margins can be a great way to avoid a crowded and cluttered UI by giving each control its own space in your layout. However, be careful not to use them too much; you might find that your layout doesn't look quite as nice when it's viewed in a different resolution.

For example, consider the layout that's shown in the image to the right. Similar to the example in the previous section, this layout is designed for a resolution of 768 x 1280. It includes two TextField controls, one near the top of the screen and the other near the bottom.

You could create this layout by using margins. You might add a bottom margin to the first TextField, which would add space between the two fields. Or, you might add a top margin to the second TextField.

Screen showing a layout that you can create using either margins or space quotas.

Here's how to create this layout using margins. The first TextField includes a bottom margin of 1010 pixels to create space between the fields.

import bb.cascades 1.0

Page {
    Container {
        background: Color.create(0.86, 0.86, 0.9)
        layout: StackLayout {}
    
        topPadding: 50
        leftPadding: 50
        rightPadding: 50
        bottomPadding: 50
        
        TextField {
            bottomMargin: 1010
            textStyle.base: SystemDefaults.TextStyles.BigText
            hintText: "Type a header here"
        }
        
        TextField {
            textStyle.base: SystemDefaults.TextStyles.BigText
            hintText: "Type a footer here"
        }
    }
}

As long as you need to consider only a single resolution, this solution works just fine. However, the image to the right shows what happens when this app is run on a device with a resolution of 720 x 720.

The bottom TextField isn't displayed because the margin of the top TextField pushes it out of view. A similar issue would occur if you chose to add the margin to the bottom TextField instead. This approach, along with other approaches that use absolute pixel values, isn't a good choice in this situation.

Screen showing an incorrect version of the layout.

A better approach might be to use space quotas to specify how much space each control uses. Space quotas determine the proportion of space that a control uses in its container, relative to the other controls in the container. By using containers for each TextField and specifying that the containers should both use the same amount of space at the top and bottom of the screen, you can create a layout that adapts more easily to different resolutions.

Here's how to use space quotas to achieve the proper layout:

import bb.cascades 1.0

Page {
    Container {
        background: Color.create(0.86, 0.86, 0.9)
        layout: StackLayout {}
    
        topPadding: 50
        leftPadding: 50
        rightPadding: 50
        bottomPadding: 50
        
        Container {
            layoutProperties: StackLayoutProperties {
                spaceQuota: -1
            }
	        TextField {
	            textStyle.base: SystemDefaults.TextStyles.BigText
	            hintText: "Type a header here"
	        }
	    }
	    
	    Container {
	        layoutProperties: StackLayoutProperties {
	            spaceQuota: 1
	        }
	    }
        
        Container {
            layoutProperties: StackLayoutProperties {
                spaceQuota: -1
            }
	        TextField {
	            textStyle.base: SystemDefaults.TextStyles.BigText
	            hintText: "Type a footer here"
	        }
	    }
    }
}

Now, the layout appears correctly.

There are other solutions that you could choose to use. A DockLayout, combined with padding, would work nicely here, too. It's important to understand all of the layout options that are available to you, so you can make the most appropriate choice for the UI that you're developing.

To learn more about margins and space quotas, see Layouts.

Screen showing a correct version of the layout.

Static asset selection

Cascades includes a static asset selector that automatically chooses the best assets (image assets and .qml files) for a device with a particular resolution. You don't need to rebuild or repackage your app to select the right assets, either; Cascades automatically selects the best set of assets for a particular device at runtime. This feature lets you create images and QML code that are designed for a specific resolution and use them automatically when you build your project. You can also use the static asset selector to choose assets based on the theme (bright or dark) that your target device is using.

To learn more about this feature, see Static asset selection.

Nine-slice scaling

Nine-slice scaling is a technique that lets you create images that can scale uniformly. You can specify the dimensions of the corners and border of the image in a special metadata file (with an .amd extension). When the image is resized (for example, to fit a different screen resolution), only the middle of the image scales; the corners and border stay the same.

By using nine-slice scaling, you can ensure that the images in your apps aren't distorted when they're viewed in different resolutions. For example, take a look at the image to the right. If this image represents a text area or chat box in your app, you might want it to be able to expand without distorting the width of the borders.

Diagram showing a text area or chat box example.

Here's what the scaled version of this image might look like. The image on the left doesn't use nine-slice scaling, but the image on the right does.

 
Diagram showing an incorrectly scaled version of the example image.
Diagram showing a correctly scaled version of the example image.
 

To learn more about nine-slice scaling and how to apply it in your apps, see Image assets.

Last modified: 2013-12-21

comments powered by Disqus