×
Namespaces

Variants
Actions

Implementing a simple View Manager with QML

From Nokia Developer Wiki
Jump to: navigation, search
Article Metadata
Code ExampleTested with
Devices(s): Nokia N8
Compatibility
Platform(s):
Symbian
Nokia Belle
Article
Created: jappit (24 Feb 2011)
Last edited: hamishwillee (30 Jan 2013)

This article shows how to implement a simple View Manager component in QML.

Wiki n8 qml viewmanager.png

Contents

The View Manager

A View Manager allows to handle all the view switching in an application.

Specifically, the simple View Manager implemented in this article allows to:

  • manage the view navigation history
  • animate the change from a view to another
  • integrate with the default QML visible property (so that no special methods need to be called)

The view history

The view history allows to track the views navigated by the user, allowing it to "go back" from a view to the previously viewed one. The following example shows how a view history works:

  • user starts from view 1
  • user goes to view 2
  • if users goes back, he returns to view 1
  • user goes to view 3
  • if users goes back again, he returns to view 1

The view animation

Animating the switching from a view to another gives the user a nice visual feedback of the action of actually moving to another "part" of an application. This can be performed with various kinds of transition:

  • fade in/fade out
  • slide in/slide out
  • and many more

The simple View Manager implemented in this article will show how to implement a simple "slide in/slide out" transition when moving from a view to another (one of the most commonly used in mobile UIs). The following approach will be used:

  • when the user moves to a new view (that does not belong to view history) the new view slides in from right, and the current view slides out to left
  • when the user moves (go back) to a view in the view history, the new view slides in from left, and the current view slides out to right

Writing the component

Let's start with an empty SimpleViewManager.qml and a SimpleViewManager.js file, that will contain the component's QML and JavaScript code. In the SimpleViewManager.qml file:

  • import the SimpleViewManager.js file:
import "SimpleViewManager.js" as SVM
  • Define a root and a child Rectangle, and define as default property the children property of the inner Rectangle: this way, all the component's children will be directly added to the inner Rectangle
Rectangle {
id: viewManager
 
default property alias content: viewsContainer.children
 
clip: true
 
Rectangle {
id: viewsContainer
anchors.fill: parent
}
}

Appending views to the View Manager

The above structure allows to define an instance of the View Manager as follows:

SimpleViewManager {
id: myViewManager
anchors.fill: parent
 
Rectangle {
id: view1
 
// this is one view
}
Rectangle {
id: view2
 
// this is another view
}
}

Adding the view animation

Two Animation objects are defined, that will animate the view switching: one for the current view (that will be moved out of the viewsContainer) and one for the next view (that will be moved in)

Rectangle {
id: viewManager
 
[...]
 
PropertyAnimation {
id: currentViewAnimation
duration : 500
property: "x"
easing.type: Easing.InQuad
}
PropertyAnimation {
id: nextViewAnimation
duration : 500
property: "x"
easing.type: Easing.InQuad
}
}

In order to properly handle all the view management, two JavaScript variables are defined:

// holds the currently displayed view
var currentView;
 
// holds the current view history
var viewHistory = new Array();

What the component needs now, is a core JavaScript function that takes care of showing a view by using the Animation blocks defined above. This is done by the following showView() function, that:

  • 'checks if a view is contained in the viewHistory array: if so, the animation should "go back", otherwise the animation should go normally and the new view must be pushed in the view history
  • sets the initial x position for the next view to be displayed
  • if the two Animations are already running (for a previously view switching that isn't ended yet), then immediately completes them
  • sets appropriate targets for the two Animation objects, using the currently displayed view and the view that needs to be displayed
  • start the Animations
function showView(nextView)
{
if(nextView.visible)
{
var isPreviousView = false;
 
for(var i = 0; i < viewHistory.length; i++)
{
if(viewHistory[i] == nextView)
{
isPreviousView = true;
viewHistory.splice(i);
break;
}
}
 
if(nextView != currentView)
{
if(currentViewAnimation.running)
currentViewAnimation.complete();
 
if(nextViewAnimation.running)
nextViewAnimation.complete();
 
nextView.x = viewManager.width * (isPreviousView ? -1 : 1);
 
currentViewAnimation.target = currentView;
currentViewAnimation.to = viewManager.width * (isPreviousView ? 1 : -1);
currentViewAnimation.running = true;
 
nextViewAnimation.target = nextView;
nextViewAnimation.to = - 0;
nextViewAnimation.running = true;
 
if(currentView && !isPreviousView)
{
viewHistory.push(currentView);
}
currentView = nextView;
}
}
}

Handling the view visibility changes

To let the component be used in the easiest possible way, the view visibile property will be used in the following way:

  • in each moment, only a view can be visibile
  • when a view becomes visible, the view that was already visible becomes invisible
  • on visibility changes, the view animations will automatically be performed

In order to do this, the component checks for visibility changes via the visibleChanged signal:

function connectViewEvents(view)
{
view.visibleChanged.connect(function() {
SVM.showView(view);
});
}

At startup, the component then performs the following operations:

  • hide all the views except the first one (that will be visible by default)
  • call the connectViewEvents for each view
Rectangle {
id: viewManager
 
[...]
 
Component.onCompleted: {
var views = viewsContainer.children;
 
if(views.length > 0) {
SVM.currentView = views[0];
 
var view;
 
for(var i = 0; i < views.length; i++) {
view = views[i]
view.visible = (i == 0);
SVM.connectViewEvents(view);
}
}
}
}

Final touches

When a new view becomes visible, the previously displayed view must becomes invisible. This operation must be performed after the slide transition has ended, so the onRunningChanged of the currentViewAnimation can be used:

PropertyAnimation {
id: currentViewAnimation
duration : 500
property: "x"
easing.type: Easing.InQuad
onRunningChanged: if(!running) target.visible = false
}

How to use the View Manager

The video below shows the View Manager in action on a Nokia N8 device.

The media player is loading...

The View Manager is implemented in a way that no special methods must be called to use its features: to display a view, it is enough to change its visible property, and the View Manager will take care of managing the view history and performing the view animations.

When adding views to the view manager, it is necessary to explicitly set their width and height, since using anchors (for instance: anchors.fill: parent) will cause animations not to properly work.

Rectangle {
width: 360
height: 640
 
SimpleViewManager {
id: myViewManager
anchors.fill: parent
 
Rectangle {
id: view1
color: "blue"
width: parent.width
height: parent.height
 
Text {
id: view1Text
text: "Go to View 2"
color: "white"
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
onClicked: view2.visible = true
}
}
Rectangle {
id: view2
color: "darkgreen"
width: parent.width
height: parent.height
 
Text {
id: view2Text
text: "Go back"
color: "white"
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
onClicked: view1.visible = true
}
}
}
}

Further considerations

This component can be easily customized in several ways, including these:

  • the animations from a view to another can be easily changed by changing the PropertyAnimation objects
  • a common toolbar (for instance, containing a back button) can be easily added, by adding its UI elements to the component's root Rectangle

Related Content

The Qt Creator project containing the code presented in this article is available here: File:SimpleViewManager.zip

This page was last modified on 30 January 2013, at 07:30.
129 page views in the last 30 days.
×