Qt Reference Documentation

Top Level Form Factors

Overview

If an application is being designed to support separate layout configurations, or form factors, it should use separate top level layout QML definitions for each of those configurations. However, you should always avoid duplication of code where possible.

Consider an application that has to be deployed to at least two devices, which both have very different screen sizes and DPI values. The two form factors of the application will share many common components and attributes, and will most likely connect to the same data model.

Therefore, the top level definitions should be quite straightforward and short, with the majority of the functionality refactored into contained components. It is important to try to avoid unnecessary duplication between these top level definitions, in order to improve maintainability.

Design Patterns

There are some patterns that you might consider when designing your top level layouts:

  • In some cases, the contents of an entire page in a smaller handset could form a component element of a layout in a larger device. Therefore, consider making that a separate component (i.e. defined in a separate QML file), and in the smaller handset, the page will simply contain an instance of that component. On the larger device, there may be enough space to show two separate items. For example, in an email viewer, if the screen is large enough, it may be possible to show the email list view, and the email reader view side by side.
  • In some cases, the contents of a view might be quite similar on all screen sizes, but with an expanded content area. In this case, it may be possible to re-use the same layout definition, if defined appropriately using anchors.

The Loader component can be used to load separate QML files based on some criteria, such as the current screen Device Category. When the application is running on a specific device, this information will not change during the application's lifetime, therefore there is no issue with memory usage or performance.

Examples

Consider the ScaleFM example. We define the top level components:


and then based on a property or function, we can select the appropriate component to load within the viewContainer:

 Loader {
     source: isTablet ? "TabletView.qml" : "MobileView.qml"
     anchors.fill: parent
 }

Notice in the example, that the stationList is used as the contents of a separate page in the handset state, but the ParentChange element is used to reparent the list view into the tablet layout.


Finally, because the page is now dynamically created, we need to ensure that it is also cleaned up correctly. So here we see the page being pushed and popped from the stack at the correct stage:



Testing

When testing the layout definitions, it is important to ensure that the layouts for all form factors are working correctly. For example, if any of the contained component layouts are modified, the top level layouts need to be re-tested. Therefore it's important to also be able to test the different configurations in a single build, even if only as part of desktop testing.

In the case of the example, reparenting the elements that are shared between alternative pages is an efficient way of ensuring that the application architecture has been implemented correctly, and also of ensuring that dynamic creation and destruction of contained elements is being handled correctly. Make sure to test application shutdown whilst viewing each page of the application separately.

For more information, see the section on Scalability Testing.