Tab Pages APP (TabBar)

June 7, 2016 — 5 Comments


This is part 4 of a series of demo apps helping you to understand Qt 5.7 for x-platform development on Android and iOS.

You should have read the blogs about my first app using Qt 5.7 Material Style, my second app (StackView Example) and my third app (SwipeView Example) before reading on.

This time I’ll explain HowTo use a TabBar – one of the new Qt Quick Controls 2.

Coming from BlackBerry10 Cascades ? TabBar is similar to a SegmentedControl.

You should have installed Qt 5.7 RC.

New to Qt 5 development ? Please read my blog series from the beginning to learn some basic stuff and to understand this app.


TabBar Example App:

  • TabBar allows to easy navigate through content
  • There are 5 Pages the User can access
  • When a Page is loaded: call init()
  • Before a Page is destroyed: call cleanup()
  • TabBar Design can be configured from Settings tapping on Floating Action Button (FAB)

The Source

This app can be downloaded as Open Source from

Project structure and .pro

The project structure is similar to my StackView or SwipeView Example Apps – we’re also using 5 Pages here for TabBar to make it easy for you to compare. Pages are named same as for the StackView and SwipeView apps, but sourcecode is slightly different.

The other Apps have used Raised and Flat Buttons inside Pages – this time I’m using a customized 48 dp Image Button:

ButtonIconActive {
    imageName: tabButtonModel[1].icon
    imageSize: 48
    onClicked: {


Button {
    id: button
    // default Image Size 24x24
    property alias imageName: theIcon.imageName
    property alias imageSize: theIcon.imageSize
    focusPolicy: Qt.NoFocus
        IconActive {
        id: theIcon
        Rectangle {
        id: buttonBackground
        implicitHeight: imageSize + 24
        implicitWidth: imageSize + 24
        color: button.pressed ? accentColor : "transparent"
        opacity: button.pressed ? 0.12 : 1.0
    } // background

Popups now are in an extra Sources directory and /tabs contains TabBars and TabButtons (QML):


main.cpp and ApplicationUI (C++) are similar to the other apps (One Page Example App, StackView Example, SwipeView Example)

TabBar Design Choices

Google Material Style Guide gives you choices HowTo design a TabBar, Qt 5.7 enables you to implement your choice:


As you can see, TabBar can be part of your ToolBar or placed below, a TabButton can be done as pure-text Button, Icon-only Button or Icon plus Text. Of course you can use TabBar without a ToolBar, too.

Customizing is easy done – this is the TabButton represented by Icon-only-Design.


TabButton {
    property color theButtonColor: accentColor
    property string theIconFolder: iconFolder
    property alias hasOverlay: colorOverlay.visible
    property real theOpacity: 1.0
    focusPolicy: Qt.NoFocus
    height: 48
        Item {
        Image {
            id: contentImage
            anchors.centerIn: parent
            horizontalAlignment: Image.AlignHCenter
            verticalAlignment: Image.AlignVCenter
            source: "qrc:/images/"+theIconFolder+"/"+modelData.icon
            opacity: colorOverlay.visible? 1.0 : theOpacity
        ColorOverlay {
            id: colorOverlay
            visible: true
            anchors.fill: contentImage
            source: contentImage
            color: index == navPane.currentIndex ? theButtonColor : Qt.lighter(theButtonColor)
    } // item

Placed inside ToolBar, ColorOverly isn’t used (invisible)

Pplaced below the ToolBar, ColorOverlay tints the Image with accent color.

TabButtons fixed vs scrolling

Sometimes not all Buttons or Text fits into available width, so it makes sense to use a scrollable TabBar:

TabButton {
    // ...
    width: tabBarIsFixed? myTabBar.width / tabButtonModel.length  
	       : Math.max(112, myTabBar.width / tabButtonModel.length)


TabBar Settings (Popup)

To configure the TabBar Settings there’s another Popup:


Open the Settings Popup from Floating Action Button (FAB):


    FloatingActionButton {
        id: fab
        property string imageName: "/settings.png"
        z: 1
        anchors.margins: 16
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        imageSource: "qrc:/images/"+iconOnAccentFolder+imageName
        backgroundColor: accentColor
        onClicked: {
    } // FAB
// ...
    function showSettings() {
        popupSettings.tabBarIsFixedSettings = tabBarIsFixed
// ...
    PopupSettings {
        id: popupSettings
        onAboutToHide: {
    } // popupSettings

PopupSettings used some new Controls: RadioButtons inside a Frame:

Frame {
    ColumnLayout {
        anchors.fill: parent
        spacing: 6
        RadioButton {
            id: radioText
            focusPolicy: Qt.NoFocus
            text: qsTr("Buttons Text only")
            checked: tabButtonDesignSettings == 0
            onCheckedChanged: {
                tabButtonDesignSettings = 0
        RadioButton {
            id: radioIcon
            focusPolicy: Qt.NoFocus
            text: qsTr("Buttons Icon only")
            checked: tabButtonDesignSettings == 1
            onCheckedChanged: {
                tabButtonDesignSettings = 1
        RadioButton {
            id: radioTextAndIcon
            focusPolicy: Qt.NoFocus
            text: qsTr("Buttons Icon and Text")
            checked: tabButtonDesignSettings == 2
            onCheckedChanged: {
                tabButtonDesignSettings = 2

As already discussed in previous articles: To make Shortcuts work well, we set Qt.NoFocus for RadioButton.

This Popup follows a Default-Button-Concept, where ‘OK‘ is default (colored with Accent Color)

Even if user clicks outside the Popup to close, changed values will be updated:

Popup {
    id: popup
    // ...
    // default behavior for this Popup: OK Button Clicked
    property bool isOk: true
	// ...
    RowLayout {
        ButtonFlat {
            id: cancelButton
            text: qsTr("Cancel")
            textColor: popupTextColor
            opacity: opacityBodySecondary
             onClicked: {
                isOk = false
        } // cancelButton
        ButtonFlat {
            id: okButton
            text: qsTr("OK")
            textColor: accentColor
            onClicked: {
                isOk = true
        } // okButton
    } // row button
    // ...
    function update() {
        if(isOk) {
            tabBarIsFixed = tabBarIsFixedSettings
            tabButtonDesign = tabButtonDesignSettings
            tabBarInsideTitleBar = tabBarInsideTitleBarSettings
	// ...
// ...
// from main.qml:
// ...
onAboutToHide: {
// ...


You can define ToolTips if you want to use this to guide your users. I have implemented ToolTip on ‘Bus’ Button (First Tab).

    ToolTip.visible: pressed
    ToolTip.delay: 500
    ToolTip.text: qsTr("Take a look at the Bus schedule")


Floating Header

Using a ToolBar together with TabBar as ‘header‘ could occupy too much space in Landscape.

Coming from BlackBerry 10 Cascades ? In Cascades you can configure TitleBarScrollBehavior as NonSticky to make the TitleBar scrollable. I implemented something similar here.

Using a Loader this is easy done:

ApplicationWindow {
    property bool isLandscape: width > height
    // ...
    header: isLandscape? null : titleBar

    Loader {
        id: titleBar
        visible: !isLandscape
        active: !isLandscape
        source: titleAndTabBarSource
        onLoaded: {
            if(item) {
                item.currentIndex = navPane.currentIndex
                item.text = qsTr("HowTo move from A to B")
    Loader {
        id: titleBarFloating
        visible: isLandscape
        anchors.left: parent.left
        anchors.right: parent.right
        active: isLandscape
        source: titleAndTabBarSource
        onLoaded: {
            if(item) {
                item.currentIndex = navPane.currentIndex
                item.text = qsTr("HowTo move from A to B")

Portrait scrolling:


Landscape scrolling:


Tandem: TabBar and SwipeView

From Google Material Style Guide: You must be able to Tap on a TabButton or to swipe from content to navigate.

From Qt 5.7 TabBar: Tabs must work together with Controls providing ‘currentIndex’.

So it’s the best way to use a SwipeView to show the content and to bind the currentIndex to TabBar.

We already discussed SwipeView in detail here. SwipeView example app uses Loader to load / unlaod current Page and next / previous Pages.

For the TabBar I did it slightly different using ‘Lazy Loading‘: at Application Start the first two Tabs are pre-loaded. All other Pages will be loaded if needed, and stay loaded while App is running.

Take a look at main.qml to see how all this stuff is implemented.

To define the TabButtons first time a Repeater is used:

Repeater {
    model: tabButtonModel
    TabButton {
        width: ...
} // repeater

Coming from BlackBerry Cascades ? There’s nothing like a Repeater.

Repeater makes it easy to iterate through a data model and create Controls. In this case the tabButtonModel is designed in main.qml:

    property var tabButtonModel: 
	    [{"name": "Car", "icon": "car.png"},
         {"name": "Bus", "icon": "bus.png"},
         {"name": "Subway", "icon": "subway.png"},
         {"name": "Truck", "icon": "truck.png"},
         {"name": "Flight", "icon": "flight.png"}]

Each data object has a ‘name’ and an ‘icon’ property and can be accessed inside TabButton using and modelData.icon.

TabBar Navigation

Similar to StackView and SwipeView Examples you can go different ways to navigate between Pages with tabs:

  • click on one of the TabButtons in TabBar
  • click on a Image Button to go to another Page (Tab)
  • click on Android System ‘Back’ key to go one Tab back to the left (this is no default behavior – ony an example what you can do with app-specific navigation)
  • swipe using your fingers to go to next Page (Tab) left or right
  • use Shortcuts (see StackView example about Shortcuts)


Using BlackBerry PRIV – or connected Bluetooth Keyboard Shortcuts making it easy to navigate to Tabs 1 … 5 or next / previous Tab:



You learned HowTo use a TabBar as another way to navigate through some Pages. It depends from your use-cases what will fit best your requirements.

Using a TabBar, a StackView or a SwipeView are great to navigate through many APPs. What if there are some areas you need to switch between ? Then a sliding Drawer will be the solution to manage even really complex APPs. Before taking a look at Qt Quick Controls 2 ‘Drawer’ – there’s another way if your app can be managed by 3 to 5 buttons: Google introduces Bottom Navigation as part of Material Style. The next example APP will customize Qt Quick Controls to use Bottom Navigation.

← Back (Swiped Pages APP)

→ Next Article (Bottom Navigation APP)

⇐ Home (Overview / Topics)

5 responses to Tab Pages APP (TabBar)


    Very nice work Ekke. New to .qml and have been fiddling with the titebar so the text updates with each page, similar to your stacked_pages_x. If you had any ideas not sure how to get something similar to {text: navPane.currentItem? navPane.currentItem.title : qsTr(“”)} working within tab_pages_x app, {property string title: qsTr(“”)} within each page’s Flickable seems to be ignored ?

    Greaty work again love the style and setting abilities.



    Thank for good article. I’m finding how to create tab application on QT android.


    In landscape mode, set header to NULL , and the loader with fixed anchors position, then scrolling up, the titlebar will be overlapped. Why? The effect looks like they are in different z axis but the code is not.


      sorry – until end of year I’ll have no time to answer questions because of heavy-load of customer projects.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s