Your BlackBerry 10 app Menu just got serious! (with Sheet, NavigationPane & Tabs)

Cascades

Guest post from Shadab R. – Ed.

bb10-app-menu-1 bb10-app-menu-2

Many applications require the Menu UI component. This is the global menu within the app which is visible when the user swipes down on the top edge of the screen. It is the place to keep global ActionItem objects like Info, Settings or Help. However, it is easy to get confused on how to actually display these resulting pages and which components to use for them; namely, between Sheet & NavigationPane. Hence, we decided to provide you a sample app on how to actually integrate and tie all these components together, especially if you had a TabbedPane with NavigationPane on the Menu.

Key differences between Sheet & NavigationPane

Before we start exploring the different options with these two UI components, we should recap the general Cascades UI guidelines behind them (respective sections are hyperlinked inline).

  • Sheet – This should be used whenever there is a break in the user’s flow. That is, anything that takes the user away from their current action(s) and navigation flow; the Sheet slides in from the bottom. Typically, a sheet is presented for things such as sending emails, taking user credentials and of course, for application menu items such as Info, Help or Settings! This is typically the easiest way to implement action items on the application menu.
  • NavigationPane – This should be used whenever there is any drill down navigation involved. You get the nice sliding transition (from the right) for free, along with the swipe gestures for navigating (peek!). In terms of the application menu, you might want to use NavigationPane instead of Sheet if you want to maintain the stack like navigation for your app. Sometimes, you might also want it if you have additional drill down navigation lists within your settings page (note that you can also have a navigation pane within a sheet). However, if you are in fact pushing navigation page objects through the application menu, especially with a TabbedPane, there are certain edge cases and work around that you would have to watch out for (mentioned at the end).

For the purpose of this blog post and the github sample code provided, we are showing the implementation of both the components. However, only one of these approaches should be chosen for the application menu and it should be a consistent behavior.

Related BlackBerry 10 Tips:

  • If you swipe back by touching the navigation pane’s back arrow, you can pop back all the pages in your navigation stack (as opposed to having to press back multiple times!).
  • The primary contents or pages of the app should not be presented through the application Menu; this area is mainly designed for items which are rarely used but accessible from anywhere in the app.

Show me some code already!

Enabling the menu is the first thing you would have to worry about. If using the navigation pane, right before we are pushing the settings page, we have to disable the application menu (to be enabled back when that page is popped). This is to ensure that there is no way to push the same settings page on top of itself.

    Menu.definition: MenuDefinition {
        id: menu
        actions: [
            ActionItem {
                title: "Info"
                imageSource: "images/ic_info.png"
                onTriggered: {
                    console.log("Info: ActionItem : onTriggered");
                    // For InfoPage, we will use Sheet
                    infoSheet.open();
                }
            }
        ]
        settingsAction: SettingsActionItem {
            onTriggered: {
                console.log("Settings: ActionItem : onTriggered");
                // For Settings, we will use NavigationPane
                var settingsPageObj = settingsPage.createObject();
                Application.menuEnabled = false;
                currentNavigationPane.push(settingsPageObj);
            }
        }
    } // MenuDefinition

And how are these infoSheet and settingsPage objects created? They can be included as attachedObjects. To show some code encapsulation, we used separate QML files here for both. They can be defined inline as well, if the respective code is within them is too trivial (but why cluster the code, right?)

    // Define the Page and Sheet objects that would be used from the Application menu
    attachedObjects: [
        ComponentDefinition {
            id: settingsPage
            source: "SettingsPage.qml"
        },
        Sheet {
            id: infoSheet
            // The following page refers to the InfoPage.qml
            InfoPage {
                id: infoPage
                // Handle the custom signal from InfoPage.qml
                onDone : {
                    infoSheet.close();
                }
            }
        }
    ] // attachedObjects

Note that the onDone signal is actually a custom signal emitted from InfoPage.qml

Page {
    id: infoPage

    // Custom signal for notifying that this page needs to be closed
    signal done ()

    titleBar: TitleBar {
        title: "Info"
        dismissAction: ActionItem {
            title: "Close"
            onTriggered: {
         // Emit the custom signal here to indicate that this page needs to be closed
         // The signal would be handled by the page which invoked it
                infoPage.done();
            }
        }
    }

    Container {
		// The rest of the Page is defined here
    }
} // Page

If you were using a sheet, this would have been enough. But if you pushed a Page using NavigationPane (like we did for this Settings page), you would have to enable the menu back on again (remember, we disabled it before we pushed it on).

TabbedPane {
    // Everything else

    Tab {
        id: tab1Handle
        title: qsTr("Tab 1")
        description: "Tab 1 Description"
        property alias navHandle: nav1

        NavigationPane {
            id: nav1

            onPopTransitionEnded: {
                console.log("Tab1 : NavigationPane - onPopTransitionEnded");
                Application.menuEnabled = true;
            }

            Page {
                // Content goes here . . .
            }
        }
    } // Tab1
    // Everything else . . .
}

bb10-app-menu-3 bb10-app-menu-4

Now, to finally address some of the concerns if you are using NavigationPane from the Menu. It should be noted that Cascades doesn’t allow adding NavigationPane directly to the global TabbedPane or to a Page object (Page can be added to a NavigationPane, but not the other way around).These limitations have been imposed by Cascades intentionally, to enforce certain UI behaviours. But we do need a NavigationPane object to push a Page onto. Hence, in this case, you are left with having to add a NavigationPane object for each and every Tab that we are showing. We also have to keep track of the handle of the currently-active Tab, just so that we know which NavigationPane object we should be pushing the new Page onto.

    property NavigationPane currentNavigationPane: tab1Handle.navHandle

    // Update the NavigationPane handle when the Tab is changed
    onActiveTabChanged: {
        currentNavigationPane = activeTab.navHandle
    }

For your coding pleasure

Phew! Yes, that may have seemed like a long blog post but it is actually much simpler when you look at the complete source files. Feel free to check out the actual code project on github right here. Compile, deploy and get going with the menus of those awesome Cascades apps of yours!

About Shadab Rashid

Application Development Consultant; passionate about user experience, consumer software products, entrepreneurship, music and people! @surashid

Join the conversation

Show comments Hide comments
+ -
  • http://www.sdknews.com/blackberry/your-blackberry-10-app-menu-just-got-serious-with-sheet-navigationpane-tabs Your BlackBerry 10 app Menu just got serious! (with Sheet, NavigationPane & Tabs) | SDK News

    […] Your BlackBerry 10 app Menu just got serious! (with Sheet, NavigationPane & Tabs) […]

  • http://www.cnbbdevgroup.com/cn/?p=8995 中国黑莓开发网

    […] 现在,最后强调一次通过菜单使用导航面板时的注意事项。注意:Cascades不允许将导航面板直接添加到全球标签面板或页面对象(可以将页面添加到导航面板中,但不能将导航面板添加到页面中)。Cascades有意强加这些限制性,目的在于执行某些UI行为。但我们确实需要一个导航面板以添加页面。因此,在此案例中,每个演示的桌面都必须添加导航面板。同时,还需记录当前运行桌面的处理状态,以便了解该将新页面添加至哪一个导航面板。 property NavigationPane currentNavigationPane: tab1Handle.navHandle // Update the NavigationPane handle when the Tab is changed onActiveTabChanged: { currentNavigationPane = activeTab.navHandle } 很高兴为您编码 是的,那看起来或许是一篇很长的博客日志,但当您浏览完完整的源文件后便会发现实际上是相当简单的。在这儿可以很轻松地检查出github上的实际代码计划。完全通过自己便可编辑、配置、整理那些烦人的Cascades应用程序菜单!   原文链接:http://devblog.blackberry.com/2013/03/blackberry-10-app-menu/ […]

  • http://www.cnbbdevgroup.com/cn/?p=9175 黑莓10应用程序菜单的问题越来越严重(包括菜单、导航面板和桌面)! | 中国黑莓开发网

    […] 原文链接:http://devblog.blackberry.com/2013/03/blackberry-10-app-menu/ […]

blog comments powered by Disqus