Activity indicators

An ActivityIndicator is used to indicate that a process is currently underway. This control is most commonly used when a task or process takes a long time to complete, or when the length of time can't be accurately determined. Unlike other controls, an ActivityIndicator is non-interactive and comes in three fixed sizes.


Screen showing an ActivityIndicator control.

Nearly all aspects of the appearance of an ActivityIndicator are fixed, and can't be changed, including the speed, size, shape, and direction of the animation.

The track that outlines the path of the animation is affected by any color or object that is placed behind it. Because the indicator is semi-transparent, it takes whatever color is placed behind it and darkens it, if possible. The device theme also affects the color of an ActivityIndicator.

Sizing

  • The size of the control is determined by the space available, and the largest of its fixed sizes is chosen to fit inside the space.
  • An ActivityIndicator won't scale beyond the three fixed sizes that are available. If the available space is larger than the control, it is centered in the space.
  • You can set the preferredWidth, minWidth, and minHeight properties, but the fixed sizes and available space take precedence.
  • The leftPadding, rightPadding, topPadding, and bottomPadding properties can't be used on this control.

Controlling the indicator

You can use the start() and stop() functions to control an ActivityIndicator. When an ActivityIndicator receives the started() signal, it becomes visible to the user, and displays a rotating animation. The ActivityIndicator is semi-transparent, and the speed of the animation is fixed. The animation continues to play until the stopped() signal is received. When an ActivityIndicator is stopped, it gradually fades until it is no longer visible.

In QML, you can use a Button with an onClicked signal handler to start and stop your ActivityIndicator.

// Create the ActivityIndicator
ActivityIndicator {
    id: myIndicator
}

// Create a Button   
Button {
    text: "Start!"
    // Use the onClicked signal handler
    // to start and stop the ActivityIndicator
    onClicked: {
        if (text == "Start!") {
            text = "Stop!"
            myIndicator.start();
        } else {
            text = "Start!"
            myIndicator.stop();
        } 
    }
}

Here's how to do the same thing in C++.

#include <bb/cascades/ActivityIndicator>
#include <bb/cascades/Button>
//...

// Create the ActivityIndicator. The
// myIndicator object is declared in the
// header as follows:
// ActivityIndicator *myIndicator;
myIndicator = ActivityIndicator::create();

// Create a button and set the button text.
// The myButton object is declared in the header
// as follows:
// Button *myButton;
myButton = Button::create()
        .text((const QString) "Start!");

// If any Q_ASSERT statement(s) indicate that the slot 
// failed to connect to the signal, make sure you know exactly
// why this has happened. This is not normal, and will cause your 
// app to stop working
bool connectResult;

// Since the variable is not used in the app, this is added 
// to avoid a compiler warning
Q_UNUSED(connectResult);

// Connect the clicked() signal to the handleClicked() slot
connectResult = QObject::connect(myButton, SIGNAL(clicked()), 
                                 this,
                                 SLOT(handleClicked()));
                                 
// This is only available in Debug builds
Q_ASSERT(connectResult);

//...

// Create the handleClicked() slot to
// capture the clicked() signal
void ButtonRecipe::handleClicked()
{
    // Control the ActivityIndicator
    if (myButton->text() == "Start!") {
        myIndicator->start();
            myButton->setText("Stop!");
        } else {
            myIndicator->stop();
            myButton->setText((const QString) "Start!");
        }
}

For more information on responding to signals, see Signals and slots.

Activity indicator examples

The following sample consists of two ImageView controls, a Button, and an ActivityIndicator.

When the button is pressed, an activity indicator is displayed over the image of the egg. The activity indicator continues to run until the button is pressed again. When the button is pressed a second time, the activity indicator stops, and the image changes to a broken egg.

Pressing the button again resets all the controls to their original state.

You can download the images for the sample here: images.zip

Animation showing an ActivityIndicator controlled by a Button.

main.qml

import bb.cascades 1.0
  
Page {
    titleBar: TitleBar {
        title: "ActivityIndicator"
    }
      
    Container {
        layout: DockLayout{}
          
        Container {
            horizontalAlignment: HorizontalAlignment.Center
            verticalAlignment: VerticalAlignment.Center
              
            Label {
                bottomMargin:100
                horizontalAlignment: HorizontalAlignment.Center
                text: "This is an egg boiling simulator"
                textStyle.base: SystemDefaults.TextStyles.TitleText
            }
            Container {
                horizontalAlignment: HorizontalAlignment.Center
                layout: DockLayout {}
                // Create an ImageView to hold the image of
                // the egg
                ImageView {
                    id: unbroken
                    imageSource: "asset:///images/egg.png"
                    horizontalAlignment: HorizontalAlignment.Center
                    verticalAlignment: VerticalAlignment.Center
                }
                // Create an ImageView to hold the broken egg
                // image. The opacity is set to 0.0 so this is
                // not visible when the app is started
                ImageView {
                    id: broken
                    imageSource: "asset:///images/broken_egg.png"
                    opacity : 0.0
                    horizontalAlignment: HorizontalAlignment.Center
                    verticalAlignment: VerticalAlignment.Center
                }
                // Create ActivityIndicator and center it
                // in the parent container
                ActivityIndicator {
                    id: myIndicator
                    preferredWidth: 130
                    preferredHeight: 130
                    horizontalAlignment: HorizontalAlignment.Center
                    verticalAlignment: VerticalAlignment.Center
                }
            }
            Button {
                topMargin:100
                horizontalAlignment: HorizontalAlignment.Center
                text: "Start cooking"
                // The onClicked signal handler controls
                // the ActivityIndicator and the visibility of
                // the ImageView controls
                onClicked: {
                    if( text== "Start cooking") {
                        text = "Look away"
                        myIndicator.start();
                    } else if(text== "Look away") {
                        text = "Clean up"
                        unbroken.opacity = 0.0 
                        broken.opacity = 1.0
                        myIndicator.stop();
                    } else {
                        text = "Start cooking"
                        unbroken.opacity = 1.0 
                        broken.opacity = 0.0
                    }
                }
            }
        }
    }
}

ActivityIndicatorRecipe.h

#ifndef _ACTIVITYINDICATORRECIPE_H_
#define _ACTIVITYINDICATORRECIPE_H_

#include <bb/cascades/Page>
#include <bb/cascades/Container>
#include <QObject>
#include <bb/cascades/Button>
#include <bb/cascades/ImageView>
#include <bb/cascades/ActivityIndicator>

using namespace bb::cascades;

namespace bb { namespace cascades { class Application; }}

/* ActivityIndicatorRecipe Description:
 *
 * Simple ActivityIndicator recipe shows how an 
 * ActivityIndicator control can be used.
 *
 */
class ActivityIndicatorRecipe: public QObject
{
    Q_OBJECT

public:
    ActivityIndicatorRecipe(bb::cascades::Application *app);
    	virtual ~ActivityIndicatorRecipe() {}

public slots:

    /**
     * Slot function to listen to the button
     */
    void onClicked();

private:
    ActivityIndicator *mActivityIndicator;
    Button *mButton;
    ImageView* mUnbroken;
    ImageView* mBroken;

    Page *root;
    Container *recipeContainer;
};

#endif // ifndef _ACTIVITYINDICATORRECIPE_H_

ActivityIndicatorRecipe.cpp

#include "activityindicatorrecipe.h"

#include <bb/cascades/ActivityIndicator>
#include <bb/cascades/Application>
#include <bb/cascades/Button>
#include <bb/cascades/Container>
#include <bb/cascades/DockLayout>
#include <bb/cascades/ImageView>
#include <bb/cascades/Label>
#include <bb/cascades/StackLayout>
#include <bb/cascades/SystemDefaults>
#include <bb/cascades/TextStyle>
#include <bb/cascades/TitleBar>

using namespace bb::cascades;

ActivityIndicatorRecipe::ActivityIndicatorRecipe
(bb::cascades::Application *app): QObject(app)
{

    Page *page = new Page();
    TitleBar *tbar = TitleBar::create().title("Activity Indicator");
    page->setTitleBar(tbar);

    Container *root = Container::create()
    		.layout(new DockLayout());

    Container *recipeContainer = Container::create()
    		.horizontal(HorizontalAlignment::Center)
    		.vertical(VerticalAlignment::Center);

    Label *introText = Label::create()
    		.text((const QString) "This is an egg boiling simulator")
    		.textStyle(SystemDefaults::TextStyles::titleText())
    		.bottomMargin(100.0);

    Container* smashContainer = Container::create()
    		.layout(new DockLayout())
    		.horizontal(HorizontalAlignment::Center);

    // Create an ImageView to hold the unbroken egg image
    mUnbroken = ImageView::create("asset:///images/egg.png")
    		.horizontal(HorizontalAlignment::Center)
    		.vertical(VerticalAlignment::Center);

    // Create an ImageView to hold the broken egg image
    // Because the broken egg image is not shown when the app is
    // started, we set the opacity to 0.0 so that it's not visible
    mBroken = ImageView::create("asset:///images/broken_egg.png")
    		.opacity(0.0)
    		.horizontal(HorizontalAlignment::Center)
    		.vertical(VerticalAlignment::Center);

    // Create the ActivityIndicator and center it in the parent
    // Container
    mActivityIndicator = ActivityIndicator::create()
    		.preferredSize(130,130)
    		.horizontal(HorizontalAlignment::Center)
    		.vertical(VerticalAlignment::Center);

    smashContainer->add(mUnbroken);
    smashContainer->add(mActivityIndicator);
    smashContainer->add(mBroken);

    // Create a button and set the text for the button
    mButton = Button::create()
    		.topMargin(100.0)
    		.text((const QString) "Start cooking")
    		.horizontal(HorizontalAlignment::Center);

    // If any Q_ASSERT statement(s) indicate that the slot failed
    // to connect to the signal, make sure you know exactly why
    // this has happened. This is not normal, and will cause your
    // app to stop working
    bool res;

    // The res variable is not used in the app, and this will
    // avoid a compiler warning
    Q_UNUSED(res);

    // Connect the clicked() signal to the onClicked() slot
    res =  connect(mButton, SIGNAL(clicked()), 
           this, 
           SLOT(onClicked()));

    // This is only available in Debug builds
    Q_ASSERT(res);

    // Add the controls to the recipe Container and set it as root
    recipeContainer->add(introText);
    recipeContainer->add(smashContainer);

    recipeContainer->add(mButton);

    root->add(recipeContainer);
    page->setContent(root);
    app->setScene(page);

}

// The onClicked() slot controls the ActivityIndicator
// and the opacity of the ImageView controls
void ActivityIndicatorRecipe::onClicked()
{

    if (mButton->text() == "Start cooking") {
        mActivityIndicator->start();
        mButton->setText((const QString) "Look away");
    } else if (mButton->text() == "Look away") {
        mButton->setText((const QString) "Clean up");
        mUnbroken->setOpacity(0.0);
        mBroken->setOpacity(1.0);
        mActivityIndicator->stop();
    } else {
        mButton->setText((const QString) "Start cooking");
        mUnbroken->setOpacity(1.0);
        mBroken->setOpacity(0.0);
    }

}

main.cpp

#include "ActivityIndicatorRecipe.h"
 
#include <bb/cascades/Application>
#include <Qt/qdeclarativedebug.h>
 
using namespace bb::cascades;
 
Q_DECL_EXPORT int main(int argc, char **argv)
{
    Application app(argc, argv);
 
    new ActivityIndicatorRecipe(&app);
 
    return Application::exec();
}

Last modified: 2013-12-21



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus