Touch vs Keyboard

Please take a look at the workflow in ‘Strict’ Mode – explained in detail here.

All works well and looks great on Touch Device and I have tried to minimze the Touch Gestures / Taps you have to do while starting a new Tracking.

Same will also work on a Keyboard Device like Q10 or Q5 – demonstrated in detail for ‘Free’Mode here.

hmmm – there’s a keyboard integrated – can we do it even faster ? Yep !

Type’n’Go TimeTracker:

G → (Alt-n) → G → G → G

That’s all 🙂

Let’s take a look how this works:

At first there’s the HomeScreen:

Q10home_G

Typing ‘G‘ will do the same as Tapping on the Action ‘go‘ – if you don’t know which Key to type, tap on the overflow menu (three dots):

Q10home_Menu_G

Please notice the small shortcut listed in top-right corner. This is only visible on a keyboard device. Developing this is easy:

ActionItem {
    id: startStopAction
    title: trackedTimeContainer.running ? qsTr("STOP") : qsTr("START")
    ActionBar.placement: ActionBarPlacement.OnBar
    imageSource: trackedTimeContainer.running ? "asset:///images/stop.png" : "asset:///images/go.png"
    onTriggered: {
        if (trackedTimeContainer.running) {
            pushTimeStopper()
        } else {
            pushTimeStarter()
        }
    }
    shortcuts: [
        Shortcut {
            enabled: trackedTimeContainer.running
            key: qsTr("s")
        },
        Shortcut {
            enabled: !trackedTimeContainer.running
            key: qsTr("g")
        }
    ]
}

This Action is a Toggle between Start and Stop, so there are two different titles, Icons and also ShortCuts.

Important: please don’t only add your shortcut this way:

key: “s”

surround the Key with qsTr() – then you can translate the key into different languages. It’s not an easy task to find unique letters through the app – esp. because there are some default keys already used (and translated) by the System to Edit, Zoom, Delete etc. Take a look at the documentation.

Back to our workflow: ‘G’ opens the next Page where you can select the Category:

Q10 what

If the selected Category is OK we simply type again ‘G‘ to go on. To select another category without moving your fingers to the Icon and Tapping you can type ‘alt n‘ to get this:

Q10altn

The Selection Marker was moved from ‘Working Time’ to ‘Work Readyness’. Typing alt-n again and again the Marker will cycle through all Categories.

Then typing ‘G‘ you can Go On to the next Page – typing ‘U‘ you can cancel (Undo) the workflow.

Shortcuts for ‘G’ and ‘U’ are similar to the Action from HomeScreen:

ActionItem {
    title: qsTr("Cancel")
    ActionBar.placement: ActionBarPlacement.OnBar
    imageSource: "asset:///images/ic_cancel.png"
    onTriggered: {
        cancelAndBack()
    }
    shortcuts: [
        SystemShortcut {
            type: SystemShortcuts.Undo
        }
    ]
},
ActionItem {
    title: qsTr("Go On")
    imageSource: "asset:///images/ic_next.png"
    ActionBar.placement: ActionBarPlacement.OnBar
    onTriggered: {
        saveAndGoOn()
    }
    shortcuts: [
        Shortcut {
            key: qsTr("g")
        }
    ]
}

Only different: ‘U’ (Undo) is a predefined SystemShortcut, where ‘G’ is a custom Shortcut.

Categories are displayed using a ListView with a simple ArrayDataModel. Besides the Category Icon there’s a green Marker Icon, This Marker Icon is only visible if Category Id == selected Id.

Categories will be selected by Tapping on an ImageView and Going On with selected Category from ListView function onTriggered{}:

onTriggered: {
    newCategory = categoryDataModel.data(indexPath)
    saveAndGoOn()
}

Nothing special.

To enable Shortcuts we have to tell Cascades that the ListView should receive Keys (input.route) and to add shortcuts to the ListView itself:

ListView {
     id: categoryList
     inputRoute.primaryKeyTarget: true
     shortcuts: [
         Shortcut {
             key: qsTr("Alt + n")
             onTriggered: {
                 toggleCategory()
             }
         }
     ]
     function toggleCategory(){
         if(newCategory < 5){
             newCategory +=1
         } else {
             newCategory = 0
         }
     }
}

‘G’oing on opens the next Page with details.

Request Focus

There are no or up to three Input Fields on the next Page: Project, Order, Task. It depends from Settings – Categories which fields will be displayed.

Q10 details

To enter data on a Touch Device you simply Tap on the field and enter the data. On a keyboard device it would be nice to enter data immediately without tapping into a field. That’s the reason why we need requestFocus().

Hint: think carefully when to request the focus, because on a Touch device the virtual keyboard will come up and perhaps this is not what user expects. So I’m always testing if working on a Device with a physical keyboard:

bool ApplicationUI::isKeyboardDevice() {
    bb::device::HardwareInfo hardware;
    return hardware.isPhysicalKeyboardDevice();
}

and here’s the code from QML:

    function requestFocusFirstField(){
        if(!app.isKeyboardDevice()){
            return
        }
        if(projectContainer.visible){
            if(projectText.text.length == 0){
                projectText.requestFocus()
                return
            }
        }
        if(orderContainer.visible){
            if(orderText.text.length == 0){
                orderText.requestFocus()
                return
            }
        }
        if(taskContainer.visible){
            if(taskText.text.length == 0){
                taskText.requestFocus()
            }
        }
    }

I’m checking if the field is visible and also if there’s already some text typed.

If visible and field is empty User can start typing immediately.

TimeTracker Shortcuts

TimeTracker only uses less easy-to-remember Shortcuts:

  • G:
    • Go / Start / Go On
  • S:
    • Stop / Stop+Go
  • U:
    • Undo / Cancel
  • E:
    • Edit
  • alt N:
    • Next Category / Next Selection
  • alt shift R:
    • Refresh
  • 1,2,3,4:
    • Select Tab #1 … #4
  • +:
    • Add new Record

Hint: to type a ‘1’ on Q10 you have to type ‘alt w’. Adding a Shortcut’1′  to an Action doesn’t work, adding ‘alt w’ works, but then also ‘alt w’ is displayed as shortcut from menu. You can use a trick: define two shortcuts and the first one will be displayed:

shortcuts: [
    Shortcut {
        key: "1"
    },
    Shortcut {
        key: qsTr("Alt + w")
    }
]

Q10short1234

Business Users want to be productive

I really recommend every developer to think carefully about using Shortcuts to simplify workflows or speed things up: BlackBerry Business App Users want to be productive !

Orientation

BlackBerry 10 Touch-Only devices can be used in Portrait or Landscape, where the Q5 / Q10 have a square screen and don’t distinguish between Portrait and Landscape.

There’s not the one-and-only-way-to-go HowTo solve the Orientation challenge.

Sometimes it helps using a DockLayout or using a StackLayout where sizes aren’t defined by size but relative using spaceQuota.

Cascades documentation gives you many hints and informations HowTo do this. So I only want to show some examples what can be done.

Simple Layout to support all

Here’s a simple ListView:

Q10 what

Z30_what

Z10_landscape

On a Q10 we have 2 rows of 3 items,

on a Z30 / Z10 we have 3 rows of 2 items in Portrait and 2 rows of 3 items in Landscape.

My default is always for Touch Screens in Portrait and the ListView Layout is defined this way:

layout: GridListLayout {
columnCount: 2
cellAspectRatio: 360/300
}

It’s a GridListLayout with 2 Columns where inside a Column a ImageView and Label are placed.
To watch for Orientation changes I added an orientationHandler to the Page:

attachedObjects: [
    OrientationHandler {
        onOrientationAboutToChange: {
            categorySelectionPage.reLayout(orientation)
        }
    }
]

As soon as orientation changes a function reLayout() was called.

function reLayout(orientation){
    if (orientation == UIOrientation.Landscape) {
        categoryList.layout.columnCount = 3
        categoryList.layout.cellAspectRatio = 360/200
    } else {
        categoryList.layout.columnCount = 2
        categoryList.layout.cellAspectRatio = 360/300
    }
}

Important: as soon as the Page was created I check if the device is square and change the parameters so it fits on the small screen – also I’m checking if the user is already holding the device in Landscape.

onCreationCompleted: {
    if (OrientationSupport.orientation == UIOrientation.Landscape) {
        reLayout(OrientationSupport.orientation)
    } else if (app.isSquare()) {
        categoryList.layout.columnCount = 3
        categoryList.layout.cellAspectRatio = 360/360
    }
}

Complex Layout to support’em all

Let’s take a look at a more complex sample. Please understand that I cannot show you all the code behind the scenes. To learn HowTo do this with Cascades you can attend a Cascades Workshop by me 😉 … or I develop the complete App for you 🙂

Here’s the first Tab from Tracked Times Details on Q10 and also Z30 Portrait and Landscape. Do you find out all the differences ?

Q10cat

Z30catportrait

Z30catlandscape

There are some Quick-Access Icons to jump to Geodata, Contact, Task/Project/Order and so on.

Q10 shows small Icons for this because there’s not so much space.

Z30 Portrait shows large icons in the bottom part of the screen, where in Landscape only the small Icons are visible and some fields are displayed at the right site of the Screen.

This Details Page is a Page with a Segmented TitleBar: 1. Category, 2. Detail, 3. Time, 4. Geo.

To switch between the Segments it’s easy on a Q10: simply use the 1,2,3 or 4 as key.

On a Z30 in Portrait with 5″ Screen it’s a long way up to the Top of the Screen, so I added a small navigation row at the bottom to easy swap between Segments. Moving the Z30 into Landscape this row disappears because there’s not enough space and also the TitleBar isn’t so far away.

Please also notice: in Portrait the TitleBar Segments are Text-Only where in Landscape I added an Icon because there’s much more space available.

Hope you got some inspiration what you can to to make your Users happy.

Themes 10.2

OS 10.2 only supports two Themes: dark and light, where the default depends from technology: on an OLED Display you must use a dark theme because this is the best to consume as less battery as possible. So Z10 and Q5 are using the light theme and Z30 and Q10 are using the dark theme.

Which Theme to use is defined in bar-descriptor.xml and only with some tricks you can change this on runtime.

OS 10.3 will be much more flexible and also add some descent colors to customize the UI. I will blog later about TimeTracker 2.x for OS 10.3.x

Most screens in TimeTracker are running out-of-the-box on dark and light theme, sometimes I’m using different Icons or different colors for Label.

//
textStyle.color: Application.themeSupport.theme.colorTheme.style == VisualStyle.Dark ?
        Color.LightGray : Color.DarkGray
//

Here’s a list in dark and light:

Z30listdark

Z10listlight

Manually inserted Times are marked yellow on dark and magenta on light theme, colors of Header is LightGray on dark and DarkGray on light theme. Modified records are colored orange on both themes.

There’s a small marker icon (Moon) to mark an Item as ‘Overnight’: this Icon is different for both themes. I’m using static asset folders to store those Icons.