Welcome to part eight of my article series on ‘Supporting BlackBerry Passport and 10.3 SDK / API’

First three parts of this article series help you to support the BlackBerry Passport from SDK / API 10.2 – the other ones are using SDK 10.3

Please read these articles before going on:

  1. Supporting BlackBerry Passport - step one 10.2
  2. Supporting BlackBerry Passport - Keyboard Shortcuts
  3. Supporting BlackBerry Passport – Fonts, Layouts, Logic
  4. Supporting BlackBerry Passport – Git, Colors and ActionBar
  5. Supporting BlackBerry Passport – Themes, SignatureAction, Touch on Keyboard
  6. Supporting BlackBerry Passport - Icons for different Resolution and Density
  7. Supporting BlackBerry Passport – Active Frames

Design Units

As a long time Cascades Developer you always have used Pixels to define sizes, margins or paddings – so the challenge is to rethink and use ‘du’.

A ‘Design Unit’ always has the same physical size on all devices, which means for higher density you need more pixel to fill the same space. Devices are grouped into ‘buckets’ by density:

  • 295 ppi (Z3, Z30): 8 buckets
  • 330 ppi (Q5, Q10): 9 buckets
  • 358 ppi (Z10): 10 buckets
  • 453 ppi (Passport): 12 buckets

8 buckets means you need 8 Pixel for each Design Unit (du) on a Z30, but 12 Pixel on a Passport. Now it’s easy to understand, why a Padding value of 48 Pixels looks different on the devices: 48 Pixel on Z30 are 6 du (48 / 8), but only 4 du (48 / 12) on a Passport.

Let’s take a look at the screen sizes in Design Units:

  • Z3/Z30: 90×160 du
  • Q5/Q10: 80×80 du
  • Z10: 76.8×128 du
  • Passport: 120×120 du

Most of us started development for Z10, so as a first step try to get the ‘du’ dividing the Pixel by 10: an Icon for ActionBars now is 8×8 du instead of 81×81 Pixel before on a Z10, but 64×64 Pixel on a Z30, 72×72 Pixel on a Q5/Q10 and 96×96 Pixel on a Passport. If you don’t want to design all sizes, provide the one with the highest density: 96×96 Pixel or to be prepared for more future devices with even higher density use 16 buckets ( 128×128 Pixel)

Images in ActionBar, Tabs, menus

In part 6 we already discussed how Cascades is looking for Images from density-dependent folders like 10ppd, 12ppd, … These folders are important if you need images for ActionBar, Tabs, Menus … where Images are only defined by their name.

Looking for an Image like ‘edit.png’ Cascades tries to find the Image from the folder bound to density:

  • Z3/Z30: 8ppd
  • Q5/Q10: 9ppd
  • Z10: 10ppd
  • Passport: 12ppd
  • <future>: 16ppd

For Images not found, Cascades is looking if there’s an Image with higher density and scales it down. If there’s only an Image found with lower density or from root, this one is used without upscaling !

Content – Images (ImageView)

What about your Images defined by ImageView ?

If you only provide the ImageSource, Cascades will try to find the right one – which means looking into your ppd folder and use the Image found without scaling. If not found, Cascades takes a look at ppd folders with higher density: if the Image was found, Cascades will scale it down. If not found Cascades takes a look at ppd folders with lower density: if found the Image will be scaled up ! This is different from ActionBar / Tab / Menu – Images where Cascades only scales down !

Attention: If the Image was found in the root folder, Cascades will use it without any scaling ! This can cause Images to become larger or smaller as expected. It’s always a golden rule: place all your Images into ppd folders ! Only Images used with fixed Pixel Size can remain in the root.

If you have to leave your Images in assets root, there’s a workaround. To guarantee same size on all devices set minWidth, maxWidth and minHeight,maxHeight for ImageView – of course using ‘du’. The example above (240×240 Pixel on passport) can be defined as an ImageView with 20 du width / height. Now Cascades knows: this Image should be 240×240 Pixel on Passport and 160×160 Pixel on Z30. Same story again: find the Image from 12ppd folder only Cascades will scale down to 160×160 Pixel on Z30 – finding the Image only as 160×160 inside 8ppd, Cascades will scale up to 240×240 Pixel on Passport ! Don’t forget to set the ScalingMethod !

Sounds confusing ? Only the first time !

Sample Project at Github

To understand it better: here’s a Cascades Project at Github to play with :)

In my sample I’m using three Images:

  • Image ‘A’ placed into 8ppd, 9ppd, 10ppd and 12ppd as 20×20 du
  • Image ‘B’ the same but only placed into 8ppd
  • Image ‘C’ the same but only available from 12ppd

To see what happens if ‘B’ or ‘C’ are NOT inside ppd folders – only at root – I placed a renamed copy at assets/root and displayed it ‘as-is’ vs scaled using min/max width/height

Here’s the result from BlackBerry Passport (12ppd):

passport_sample

From ‘B’ in the middle you see 160×160 px are smaller then 20 du (240×240) if used unscaled from root.

… and here’s how it looks from Z30 (8ppd):

z30_sample

From ‘C’ in the middle you can see the too large image with 240×240 unscaled on Z30.

The ActionBar on Z30 is OK because ‘C’ was downscaled automatically – on Passport ‘B’ is too small because Cascades doesn’t upscale for ActionBar Images.

You still need some Images Device-specific for Absolute Layouts or fine-tunied backgrounds or special Covers ? Place them inside static assets folders like 1440×1440 for the BlackBerry Passport.

Have fun with BlacpBerry Passport and 10.3

Welcome to part seven of my article series on ‘Supporting BlackBerry Passport and 10.3 SDK / API’

First three parts of this article series help you to support the BlackBerry Passport from SDK / API 10.2 – the other ones are using SDK 10.3

Please read these articles before going on:

  1. Supporting BlackBerry Passport - step one 10.2
  2. Supporting BlackBerry Passport - Keyboard Shortcuts
  3. Supporting BlackBerry Passport – Fonts, Layouts, Logic
  4. Supporting BlackBerry Passport – Git, Colors and ActionBar
  5. Supporting BlackBerry Passport – Themes, SignatureAction, Touch on Keyboard
  6. Supporting BlackBerry Passport - Icons for different Resolution and Density

Active Frames

You know if you’re switching from one App to another without closing the current App, the App will be minimized.

If you’re doing nothing Cascades will take a snapshot of your current screen and show this one minimized.

Of course it looks much better if you design a special screen and this is easy done by using a SceneCover. SceneCovers have special sizes and there are some recommended layouts like Header or Grid. Please take a look at Cascades documentation where you also will find the exact sizes.

BlackBerry Passport is the first device supporting two different Active Frames: a large one and a small one:

  • Large-sized Active Frame: 440×486 px
  • Small-sized Active Frame: 440×195 px

MultiCover

To support both sizes you have to use a MultiCover, where inside your MultiCover you can use:

  • Two SceneCovers
  • One SceneCover plus one ApplicationViewCover

Two SceneCovers allow you to design the large and small sized ActiveFrame by yourself or you’re only designing one size and let Cascades create the Cover using the (minimized) top-left part of your current Page.

Two SceneCovers:

import bb.cascades 1.3

MultiCover {
    id: multiCover

    SceneCover {
        id: bigCover
        MultiCover.level: CoverDetailLevel.High
        content: Container {
            // your layout
        }
        function update() {
            // do your update stuff
        }
    } // sceneCover HIGH
    
    SceneCover {
        id: smallCover
        MultiCover.level: CoverDetailLevel.Medium
        content: Container {
            // your layout
        }
        function update() {
            // do your update stuff
        }
    } // sceneCover MEDIUM

    function update() {
        bigCover.update()
        smallCover.update()
    }

} //  multiCover

One SceneCover plus one ApplicationViewCover:

import bb.cascades 1.3

MultiCover {
    id: multiCover

    SceneCover {
        id: bigCover
        MultiCover.level: CoverDetailLevel.High
        content: Container {
            // your layout
        }
        function update() {
            // do your update stuff
        }
    } // sceneCover HIGH

    ApplicationViewCover {
        id: appViewCover
        MultiCover.level: CoverDetailLevel.Medium
    }

    function update() {
        bigCover.update()
    }

} //  multiCover

CoverDetailLevel High or Medium decides which one will be used. The update() function is used to update the content dynamically – but this is the same as already known from 10.2

Perhaps you ask why does Passport support two different sized Active Frames ?

Screenshot CoverDetailLevel.High

cover_high

As soon as there are more then 6 minimized Apps, the last ones will be smaller und use the layout fromCover with Screenshot CoverDetailLevel.Medium:

cover_medium

In this case the CoverDetailLevel.Medium was provided by ApplicationViewCover – something is cut at the right site and this minimized view will change if another Page is on top. So it will be better to design a second SceneCover in this case.

Next part of this series will tell you more about ‘du’ – Design units and designing layouts for 10.3 and BlackBerry Passport.

Have fun.

Welcome to part six of my article series on ‘Supporting BlackBerry Passport and 10.3 SDK / API’

First three parts of this article series help you to support the BlackBerry Passport from SDK / API 10.2 – the other ones are using SDK 10.3

Please read these articles before going on:

  1. Supporting BlackBerry Passport - step one 10.2
  2. Supporting BlackBerry Passport - Keyboard Shortcuts
  3. Supporting BlackBerry Passport – Fonts, Layouts, Logic
  4. Supporting BlackBerry Passport – Git, Colors and ActionBar
  5. Supporting BlackBerry Passport – Themes, SignatureAction, Touch on Keyboard

Application Icons

In 10.2 you only needed one application Icon of 114×114 px – now with 10.3 and supporting more devices with high density and larger screens, you need some more:

  • Z10: 110×110 px
  • Z3 / Z30: 96×96 px
  • Q5 / Q10: 90×90 px
  • Passport: 144×144 px

Your application will still work using your old 114×114 px application icon, but it’s recommended to provide 4 Icons.

To add the Icons copy them into your project folder as you did with the app Icon before. Please open your bar-descriptor.xml, go to ‘Application’ tab and add the Icons.

app_icons

Cascades will select the right one. Find more on Application Icons from Cascades docs here.

In-App Icons

In 10.2 we used 81×81 px Icons for Tabs and ActionItems in ActionBar and 61×61 px Icons in components.

You can still run your App with these Icons, but because of higher density some Pages won’t look good on BlackBerry Passport. (Images too small)

I already described that you can use a workaround and scale the Icons by yourself: check if device is Passport and set minWidth, maxWidth, minHeight, maxHeight to a higher value and let Cascades upscale the image:

ImageView {
    property int imageSize: app.isPassport()?92:61
    imageSource: "asset:///images/server_color.png"
    minWidth: imageSize
    maxWidth: imageSize
    minHeight: imageSize
    maxHeight: imageSize
    scalingMethod: ScalingMethod.AspectFit
    verticalAlignment: VerticalAlignment.Top
    horizontalAlignment: HorizontalAlignment.Center
}

This works as a starting point but isn’t optimal. To be prepared for the future and to provide a great looking UI you have to design Icons in different sizes.

Cascades groups Devices by density (ppi – pixel per inch) and instead of Pixel we’re now using ‘du’ Design Units, where one ‘du’ always has the same size on a screen: 10 pixels on a Z10 are the same as 8 pixels on a Z30, 9 pixels on a Q10 or 12 pixels on BlackBerry Passport. The grouping is done by ‘ppd’ (Pixel per Design Unit), so we have these groups:

  • 10 ppd: Z10 (768×1280 px, 356 ppi)
  • 8 ppd: Z3 / Z30 (720×1280 px, 295 ppi)
  • 9 ppd: Q5/Q10 (720×720 px, 330 ppi)
  • 12 ppd: Passport (1440×1440 px, 453 ppi)

Here are the recommended sizes for 10.3:

  • ActionItems, Menus, Tabs: 8×8 du
  • Components: 7×7 du
  • Small Buttons: 6×6 du

Let’s take a look at the ActionItems. What does 8×8 mean in reality – what sizes must your Icons have ?

  • 10 ppd (Z10): 80×80 px
  • 8 ppd (Z3 / Z30): 64×64 px
  • 9 ppd (Q5 / Q10): 72×72 px
  • 12 ppd (Passport): 96×96 px

BlackBerry 10 App development started with Z10 and 81×81 pixels. Now the Z10 belongs to the 10 ppd buckets where 8×8 du is the same as 80×80 px because 1 du == 10 px.

Please take a look at the excellent documentation from Cascades to learn more.

Supporting different resolution / density is a pain

… but you’re not alone ;-)

If all this density and screen size – stuff is new to you, it’s a good idea to read about it from other platforms, too.

Android

Developing for Android ? Then you have to deal with dp (Density Pixel) and much more different sized devices out there.

Here’s the Android documentation HowTo support multiple screen sizes

android-screens-ranges

Android also groups devices per density: ldpi, mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi. All is measured in ‘dp’ (density pixel) which is similar to ‘du’ design units.

iOS

iOS developers  also started easy supporting only one screen size and density. Then it goes on larger devices and also higher density (Retina displays).

There’s one difference: iOS developers started using ‘points’ and not ‘pixel’. At the beginning with first iPhone one point == one pixel on a 320×480 px screen.

For the higher resolution devices like iPhone 6 there’s a scale-factor of 2 which means 375 × 667 points were rendered as 750 x 1334 px to fit on a 326 ppi screen. With iPhone 6+ it’s even more complicated: now the scale-factor is 3: iPhone 6+ has 375 × 667 points, rendered as 1242 × 2208 px where the device in reality has 1080 × 1920 px, so there’s a downsampling / 1.15. Here’s a site from Paint Code explaining this in detail.

Perhaps now you understand why there are x1, x2, x3 Icon sets available for iOS developers. Great looking Icons in x1, x2 and now x3 are available from Glyphish – some are also looking great on BlackBerry 10.

BlackBerry 10.3

There’s a reason why I wrote about Android and iOS: you can see it’s a common challenge to support devices of different physical sizes and different density. Now with BlackBerry 10.3 and the BlackBerry Passport we also must prepare our apps and this means:

  • more work
  • perhaps more costs to design Icons, Images, Backgrounds
  • restructuring of layouts
  • and much more.

Because of this the first three parts of this series was HowTo go on with 10.2 as a first step to get some more time to port your apps to 10.3 carefully without pressure. Comparing Cascades with other platforms the Cascades team did a great job. I will write some more blogs next weeks to provide tips and tricks HowTo port your apps.

The real hard work is porting complex apps from 10.2 to 10.3 – creating a new 10.3 app from scratch is much more easier.

Let’s go on with the ActionItem / Menu / Tab – Icons. All Icons will be stored in special folders:

  • assets/8ppd
  • assets/9ppd
  • assets/10ppd
  • assets/12ppd
  • assets/16ppd

Inside these folders it’s the same as with static assets: use exactly same subfolders and names as before. Of course it may take some time to get all your Icons designed for all sizes. Don’t worry – you can do your work step-by-step. Cascades uses a fallback strategy to find an Icon not provided in optimal size. Perhaps you’re wondering about the 16ppd folder ? There’s no device currently with such a high density but in Cascades documentations sometimes 16ppd was mentioned. So it may be a good idea to also provide Icons for 16ppd – it’s less work do design them now then in a year or so. (16 ppd means 128×128 px)

1st step: move all from root to assets/10ppd

All your Icons were designed for Z10 originally – so you should move them to the 10ppd folder. It’s important to move them out of the assets root folder – this will make it easier for Cascades to pick the right one. As soon as you start using ppd folders all Icons inside a ppd folder should not be in assets root !

In my app only some special background images are now inside assets/images and also inside device-specific folders like 1440×1440 or 720×720.

2nd step: create assets/12ppd folder

We want to start supporting BlackBerry Passport because it’s the first new Device – so we need Icons for 12 ppd.

3rd step: copy Icons from Cascades Icon Set

If you’re using Icons provided by Cascades as Icon Set for BlackBerry 10, please download the new one for 10.3 from here.

bb10_icon_download

You’ll notice that all Icons are now 96×96 px instead of 81×81 from 10.2. 96×96 fits perfect for BlackBerry Passport, so copy the ones you’re using into assets/12ppd/images.

Now you have a good starting point and can add more ppd-specific Icons when they’re ready.

How does Cascades select Icons

With all these folders it’s a good idea to look behind the scenes and to know how Cascades will pick the right Icon. There are some rules you should know:

  • Cascades downscales Icons from higher density
  • Cascades can use, but doesn’t upscale Icons from lower density

Having all Icons in assets/10ppd and some Icons also in assets/12ppd: what happens running the App on BlackBerry Passport ?

At first Cascades looks into the assets/12ppd/images folder and picks the Icon if found.

As next Cascades checks if there are Icons with a higher density – so if you placed the Icon with 128×128 px into assets/16ppd/images Cascades will take this one and downscale to 96×96 px automatically.

If nothing found with higher density, Cascades will go down one step and finds the Icon inside assets/10ppd/images. This is lower density so the Icon will be used unchanged as 81×81.

Knowing that Cascades downscales it makes sense to start with one Icon in highest density and to test if it looks good on all devices. If all is Ok you don’t have to design all the other ones. For new Apps running under 10.3 this will be the way-to-go. To port Apps from 10.2 take the steps from above.

Icons from C++ missing ?

All I described above works perfect from QML with images referencing assets/images.

If you set Icons from C++ you have to change your code !

Probably there are some use-cases where you assigned Icons similar to this:

QString imageSource = QDir::currentPath() + "/app/native/assets/images/titlebar/";
.....
imageSource += "wifi.png";
.....
image->setImageSource(imageSource)

This works well with static assets folders used before. Static assets are merged at startup, so th assets are available from root.

Now having more then one folder with same images this won’t work anymore.

There’s a new method ‘resolveAssetPath(Url)‘ at Application class for 10.3:

QString imageSource = "images/titlebar/";
.....
imageSource += "wifi.png";
.....
image->setImageSource(Application::instance()->resolveAssetPath(imageSource));

While developing and running your app on Device from your Momentics IDE take a look at the Console where Cascades logs some info about images and pathes.

No best path found for images/titlebar/wifi.png , will use fallback path
AssetPathResolver::resolveAssetPath: Did not find any asset for basePath= /apps/xxx/native/assets/ ,
filePath= 10ppd/images/titlebar/wifi.png

In this case Cascades is looking inside default 12ppd for the image and didn’t found one. So uses fallback path and found Icon from 10ppd path.

Next parts will be on ActiveFrames and layouting using ‘du’ (Design Units)

stay tuned …

 

Welcome to part five of my article series on ‘Supporting BlackBerry Passport and 10.3 SDK / API’

First three parts of this article series help you to support the BlackBerry Passport from SDK / API 10.2 – the other ones are using SDK 10.3

Please read these articles before going on:

  1. Supporting BlackBerry Passport - step one 10.2
  2. Supporting BlackBerry Passport - Keyboard Shortcuts
  3. Supporting BlackBerry Passport – Fonts, Layouts, Logic
  4. Supporting BlackBerry Passport – Git, Colors and ActionBar

Switching themes

In part #4 we’ve seen that some pages won’t look so good in 10.3 because of bright ActionBar.

Here’s the Home Page of my TimeTracker App using the new compact ActionBar:

compact_actionBar2

I have to redesign this page for the bright theme without using black background. (Will do this later – needs some work on images)

As a first step I made the Theme configurable from settings – so users on Passport can switch to the dark theme:

settings_wow_dark

In my settings data I’m storing ‘Default’, ‘Dark’ or ‘Bright’ and check this at startup. app.visualStyle() returns my settings value.

I’m also calling this function immediately after saving the settings – Cascades dynamically changes the style.

function setVisualStyle(){
    if(app.visualStyle() == "Default"){
        return
    }
    if(app.visualStyle() == "Dark"){
        if (Application.themeSupport.theme.colorTheme.style == VisualStyle.Bright) {
            Application.themeSupport.setVisualStyle(VisualStyle.Dark);
        }
    } else {
        if (Application.themeSupport.theme.colorTheme.style == VisualStyle.Dark) {
            Application.themeSupport.setVisualStyle(VisualStyle.Bright);
        }
    }
}

There’s one rule: on devices using OLED  displays it’s not recommended to use the bright style, so I’m hiding this settings option:

QML

Container {
    id: visualStyleContainer
    visible: !app.isOrganicDisplayTechnology()
}

C++

bool ApplicationUI::isOrganicDisplayTechnology()
{
    bb::device::DisplayInfo display;
    return display.displayTechnology() == DisplayTechnology::Oled;
}

On a Z30 the user has no chance to switch to the bright theme, but on BlackBerry Passport users can toggle between dark and bright.

I also changed the Home Page to display only one button (Start or Stop) in the middle between TabMenu and ActionMenu – so it looks like the Signature ActionItem – only using a larger one. Here’s how it looks now using the dark theme:

home_onebutton_dark

Don’t use disabled Signature Actions

I already wrote about Signature ActionItems in part #4 of this series.

There may be situations where your Signature Action will be disabled – per ex. no data to send. Disabling ‘normal’ ActionItems is easy – simply set enabled to false. But using a Signature Action this doesn’t look well – even if the user has hidden all ActionItem Labels what’s possible in 10.3 from Device Settings.

Here’s an example how enabled / disabled SignatureActions are looking from bright or dark theme:

signature_disabled

Because the background color of a Signature Action remains the same for disabled Actions the difference between both states isn’t always easy to recognize. So for me it’s clear I never will disable a Signature ActionItem.

On the other side: having an enabled Signature Action telling the user after tapping on it that there’s no data to send isn’t the best solution ;-)

Unfortunately the ‘Signature’ property of an ActionItem can only be set once while creating the ActionItem so you cannot switch between OnBar and Signature.

Here’s how I’m dealing with this. Example is from TimeTracker’s Server Queue: sometimes there’s data inside the queue – sometimes not. If there’s data and network coverage TimeTracker will send queued data out automatically. Perhaps something went wrong and the user wants to trigger it manually – so there’s the ActionItem ‘Try again’.

If there’s nothing in the Queue I’m using a ‘normal’ disabled ActionItem:

queue_empty

If there’s some data,  the ActionItem was changed into an enabled Signature ActionItem:

queue_with_content

Now both states are easy to distinguish :)

attachedObjects: [
     ActionItem {
        id: tryAgainAction
        title: qsTr("Try again")
        imageSource: "asset:///images/try_again.png"
        ActionBar.placement: ActionBarPlacement.Signature
        onTriggered: {
            // do your stuff
        }
    }
]
actions: [
    ActionItem {
        title: qsTr("Network")
        imageSource: "asset:///images/info_cloud.png"
        ActionBar.placement: ActionBarPlacement.OnBar
        onTriggered: {
            // do your stuff
        }
    },
    ActionItem {
        id: tryAgainActionDisabled
        title: qsTr("Try again")
        enabled: false
        imageSource: "asset:///images/try_again.png"
        ActionBar.placement: ActionBarPlacement.OnBar
        onTriggered: {
            // dummy
        }
    },
    ActionItem {
        id: adminAction
        title: qsTr("Admin")
        imageSource: "asset:///images/server.png"
        ActionBar.placement: ActionBarPlacement.OnBar
        onTriggered: {
            // do your stuff
        }
    }
]

There are now two Actionitems: one inside actions [ ] the other one as attached Object.

If the state changes I’m swapping the ActionItems. There’s no problem to remove / add the same Action more then one time because the removed Action still has the current Page as parent and can be reused.

if(tryAgainEnabled){
    removeAction(tryAgainActionDisabled)
    addAction(tryAgainAction)
} else {
    removeAction(tryAgainAction)
    removeAction(adminAction)
    addAction(tryAgainActionDisabled)
    addAction(adminAction)
}

I cannot insert an ActionItem at a specific position on ActionBar, so I’m also removing the adminAction and add again after adding the disabled tryAgainAction.

Please note: Adding the Signature ActionItem I don’t have to do this because a Signature Action always will be positioned in the middle.

Touch Enabled Keyboard and Scrolling (ListView, ScrollView)

How cool it is to scroll through pages from your touch enabled keyboard is easy to test:

Open the Browser and scroll through a long Page. If you need more space: rotate the Passport and scroll from the (now vertical positioned) keyboard.

Go back to your app and try to scroll through your Pages – if using ListView or ScrollView this should work.

uuups – some Lists or ScrollViews don’t scroll

At first I was thinking there’s a bug (Tested using a pre-release SDK and Simulator).

Then tried to find out which Pages scroll and which not – and finally found out the reason and it makes sense. So please don’t blame Cascades if a Page isn’t scrolling out of the box.

Remember: we’re on a Keyboard and Keyboard events are always working on the field having the Focus. If you want to enter a word into a TextField you have to Tap on the field or your app must use requestFocus() !

Same with Touch Events from your Passport Keyboard. In most Pages it will simply work, because the ScrollView or ListView is the first UI Control getting the focus automatically.

But this isn’t always true. I’m running into situations where a Page is structured this way:

  • Page
    • ScrollView disabled
      • Container for content if no-data-available
    • ListView
      • ListItems

Opening this Page with data in your List doesn’t scroll from keyboard because the ListView doesn’t have the Focus. The ScrollView has the Focus, but nothing to scroll because it’s disabled.

Now it’s up to you to manage the Focus if you’re running the app on a device like Passport where you can touch on the Keyboard: use Signals/Slots or functions.

function requestFocusToScrollTheList(){    
    if (dataModelTracked.size() && app.isKeyboardDevice()) {
        trackedList.requestFocus()
    }
}

Hint: don’t set the focus from onCreationCompleted{} – the Page must be visible before requesting the focus will work.

Now also users of your app can benefit from the cool scrolling function using touch gestures on BlackBerry Passport :)

It’s worth to support this – you know there will be the BlackBerry Classic later this year using a Trackpad besides the screen – I don’t know but could imagine it will work similar.

More Gestures on Keyboard

Scrolling is a built-in feature, but you can add your own touch functionality.

Here per ex. HowTo detect if the user swiped horizontally:

eventHandlers: [
    TouchKeyboardHandler {
        id: touchKeyboard
        property int startX
        property int stopX
        onTouch: {
            if (event.touchType == TouchType.Down) {
                startX = event.screenX
                return
            }
            if (event.touchType == TouchType.Up) {
                stopX = event.screenX
                var distance = Math.abs(stopX - startX)
                if (distance > 360) {
                    console.debug("Swiped horizontally " + distance)
                } else {
                    console.debug("distance too short")
                }
                return
            }
        }
    }
]

I’m testing if the user moved his fingers horizontally more then 360 px (around 25% of width of keyboard) – if device is in Landscape you must reduce the value.

Using Touch Events isn’t easy – please take a look at Cascades documentation, because this isn’t covered by this article series.

 

Next part will focus on Design Units. Have fun with BlackBerry Passport.

First three parts of this article series help you to support the BlackBerry Passport from SDK / API 10.2.

Please read these articles before going on:

  1. Supporting BlackBerry Passport - step one 10.2
  2. Supporting BlackBerry Passport - Keyboard Shortcuts
  3. Supporting BlackBerry Passport – Fonts, Layouts, Logic

Now we’ll go one step further and switch over to 10.3 API. This is always a great challenge HowTo manage different APIs – doesn’t matter if you’re developing for Android, iOS or BlackBerry 10 – esp. if you’re knowing that you have to maintain a project for different API a longer time. This month (September 2014) only BlackBerry Passport will run OS 10.3.0 – at the end of this year (November 2014) OS 10.3.1 is expected and will be available for all devices in the market. If it will take around 3 months to be available in most countries – so there will be a minimum timeframe of 6 – 9 months where we have to support 10.2 and 10.3.

Normaly I’m waiting some time before switching to the next API level, but this time OS 10.3 is so different from 10.2 and gives us more ways to provide good looking apps, I will bring all my apps to 10.3 very soon.

There are many ways to manage different API levels. I’m not a friend of any pre-processors and dealing with if 10.2 then this – if 10.3 then this.

10.3 is so different – there will be many cases where I have to re-layout Pages completely or restructure my QML Files or rethinking what using DU’s (Design Units) means in reality. The Business Logic (C++) will be nearly the same, but UI (QML) changes will end in some more long nights ;-)

Using Git Branches to manage API Levels 10.2 and 10.3

One year ago I wrote an article HowTo manage different API levels using Git branches and cherry-picking.

So I created a Branch for current 10.2 Development where Master is used for newest API Level (10.3).

git_repos_10_2_3

10.2 API Branch and 10.3 Master are both checked out as two projects in Momentics IDE. To make this possible I changed the Eclipse Project name inside .project:

<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
    <name>timeTracker103</name>
    // ...
</projectDescription>

Here are both projects inside Momentics IDE:

eclipse_projects_10_2_3

Hint: rename the Launch Configurations – Momentics is using the entry point name which in both cases is ‘timetracker’

launch_config

I like it to have both projects parallel in one IDE – then it’s easy to deploy and test both  APIs without checking out a Branch, refreshing / cleaning the Project,  rebuild …

Some fresh (Branding) Color

Now to start with 10.3 specific things the easiest one is to use some branding color. Cascades documentation explains how colors are working in 10.3 – let’s define a Primary Color in your bar-descriptor.xml. The documentation provides some sample colors good looking on bright and dark themes. You should always test your color scheme on dark and bright !

primary_color

Using this Primary Color Cascades will calculate all other Colors, Gradients and Font Colors for you. Let’s take a look at some screenshots after setting of a Primary Color:

Selected Tab from TabbedPane:

tabbed_pane_green

TitleBar Title, Gradient (Delimiter) and ToggleButton on bright theme (Passport) and dark theme (Z30):

title_bar_green

CheckBox and Custom Pickers on bright theme (Passport) and dark theme (Z30):

checkbox_picker_green

Isn’t this easy to get your app branded ? The really cool part is, that Cascades generates a complete UIPalette for you behind the scenes and you can use all properties from this UIPalette, per ex.:

Container {
    background: ui.palette.primarySoft
    Label {
        text: "Primary Soft " + Color.toHexString(ui.palette.primarySoft).toUpperCase();
    }
}

Now if you’re changing your branding color, all Containers with primarySoft color will get the new one. Same is with Fonts – you have access to all generated values. I’m not a Designer and sometimes it’s not easy to find the right colors – relying on Cascades UIPalette I know they all match :)

103_color_palette

Another great 10.3 feature: dynamic switching of Themes. In 10.2 you – as the developer – have to decide if you’re using the bright or dark theme or the default one. Default theme on OLED displays is dark – on other displays is bright, per ex. BlackBerry Passport default theme is bright and Z30 default theme is dark. There’s one golden rule: Using a dark theme is always OK – bright theme should not be used on AMOLED displays, because dark theme is optimized for better battery usage.

In 10.3 you can add a Theme-Switch to your Settings and allow users to switch the Theme:

Button {
    text: "Switch theme"  
    onClicked: {
        if (Application.themeSupport.theme.colorTheme.style == VisualStyle.Bright) {
            Application.themeSupport.setVisualStyle(VisualStyle.Dark);
        }      
        else {
            Application.themeSupport.setVisualStyle(VisualStyle.Bright);
        }
    }
}

You should warn the user if setting a bright theme on OLED.

I’m always supporting both themes. Sometimes it wasn’t easy to set Font colors and backgrounds – now using UiPalette you’ll always use the right one.

10.3 ActionBar

ActionBar in 10.3 gives you more flexibility.  Taking a look at 10.3 native apps like Calendar you’ll find the new Signatur Actionitem:

specialAction

The Signature ActionItem will always be in the middle of your ActionBar and use your Color (see above) as background. You can also set the color by yourself, but it’s recommend to use the default one. TimeTracker App will give the user the freedom to change between bright or dark Theme, but UIPalette will be static.

There’s also a new way to hide most part of your ActionBar – only the overflow menu and Tabs are visible.

Page {
    id: homePage
    actionBarVisibility:ChromeVisibility.Compact
    // ...
}

I will use this from TimeTracker’s HomePage where I have my own big buttons to Start or Stop a Time:

compact_actionBar

I have to redesing this Page for 10.3 and only place one big button in the midle – this will mimic the Signature ActionItem. (Also – as already written I will redesign the Page to better fit the bright theme from Passport where the ActionBar isn’t anymore with dark background as before.)

Taping on START Button, there will follow three Pages you normally only tap on the Action or type ‘g’ for GO on your Keyboard.

Changing this default action as Signature:

ActionItem {
    title: qsTr("Go On")
    ActionBar.placement: ActionBarPlacement.Signature
    // ...
}

Now take a look at these three Pages with or without a Signature Action:

actionbar_no_signature

actionbar_signature

Have fun with 10.3 and stay tuned … this was only the beginning – there will be more in this series to learn about the new features.

This is Part 3 of my ‘Support BlackBerry Passport’ series – you should read the other parts first:

  1. Supporting BlackBerry Passport - step one 10.2
  2. Supporting BlackBerry Passport - Keyboard Shortcuts

This article is the last one with some tips and tricks HowTo support the Passport from 10.2 SDK / API – part 4 will start using 10.3 SDK / API.

Most screenshots again are from my TimeTracker App – some are from one of my Conference2Go Apps: IoT Conference.

Let’s start with a ListView, where I displayed tracked time logs. Running on a Z30 the list looks different for Portrait and Landscape:

Z30-list-portrait

In Portrait the most important informations are visible from first row:

  • Time Category Image
  • Time tracked from HH:MM … to HH:MM
  • Duration HH:MM
  • Marker Image if tracked ‘over night’

second row gives some short information on Customer name (if there’s a customer connected) and Time Category Name.

Rotating to Landscape gives you more space to display some words from

  • Project (if available)
  • Order (if available)
  • Task (if available)

Z30-list-landscape

What to do on the Passport ? By default I’m using the Portrait Layout, but in this case there would be much empty space on the right side of the screen – so I decided to use the Landscape Layout as default layout for Passport. Here’s the result:

passport-list

Before Passport the layouting was easy done: the Container containing the Label fields for Landscape was only visible if device was rotated to landscape:

Container {
    id: column2Container
    visible: OrientationSupport.orientation == UIOrientation.Landscape
    layoutProperties: StackLayoutProperties {
        spaceQuota: 1.3
    }
    // Label .....
} // end column2Container

The Container becomes visble in Landscape – using spaceQuota arranging the available space for all the content displayed in StackLayout with orientation LeftToRight.

To get this also visible on Passport you could think I only had to change the visible property:

Container {
    ...
    visible: app.isPassport() || OrientationSupport.orientation == UIOrientation.Landscape
    ...
} // end column2Container

Unfortunately it’s not so easy because this Container is part of an ListItem and from inside a ListItemComponent I don’t have access to C++ methods, so app.isPassport() always will return false. To make it run we have to delegate this to the ListView where the ListItemComponent lives in:

ListView {
    id: trackedList
    // ...
    property bool column2Visible: app.isPassport() || OrientationSupport.orientation == UIOrientation.Landscape
    // ...
    listItemComponents: [
        ListItemComponent {
            type: "item"
            CustomListItem {
                id: itemRoot
                dividerVisible: true
                highlightAppearance: HighlightAppearance.Full
                TrackedListItemContainer {
                    // extra QML file layouting our ListItem
                } // end outerItemContainer
            } // end itemRoot
        }, // end ListItemComponent item

    ] // end listItemComponents
    // headerItem
    // onTriggered{} and other functions
} // end ListView

Now we can access the property from inside the ListItemComponent (TrackedListitemContainer):

Container {
    // ...
    visible: itemRoot.ListItem.view.column2Visible
    // ...
} // end column2Container

At the end it’s easy as soon as you understood how ListItemComponents are working.

UI on Passport’s High-Density (453 dpi) screen looks great :)

Even small Fonts are looking fine. Tap on the screenshot above  and zoom in to verify.

Please be aware that this high density can be a problem for users – not all eyes are able to read such small fonts and not everyone uses high end glasses to make it readable.

In my apps I’m following the UI Guidelines and I’m using SystemFontStyles like TitleText, SubTitleText, … and it’s up to the OS to choose the font and size.

On Z30 it’s very rare to hear users complaining about too small fonts, but on high-density devices like Passport this can happen. Fortunately users can change this from System Settings | Display:

Settings_Display8vs14

Changing this Font Size immediately affects all apps – even already running apps.

In many cases you have nothing to do if your design follows the rules on adaptive layouting. Here are screenshots from my IoT Conference App:

Sessions using default font size of 8:

iotconf_list_8

and here the same list with font size of 14:

iotconf_list_14

Hint: this conference app must be slightly  tuned for Passport and I haven’t done this yet: Icons are too small – but text is working for all sizes.

Back to my TimeTracker App where the List Layout is very specific and won’t survive larger fonts:

passport_14_problem

Now the Duration is missing because there’s not enough space anymore using such a large font. Changing to ’12’ duration will be partly there – changing to larger then ’14’ from…to time will only be visible partly. Both informations are important and should always be visible independent from Font Size.

Here’s a solution HowTo survive such kind of layouts:

Label {
    text: ListItemData.hourMinuteLocal + "-" + ListItemData.hourMinuteLocalStop
    textFit.maxFontSizeValue: itemRoot.ListItem.view.titleTextMaxSize
    textStyle.base: SystemDefaults.TextStyles.TitleText
    textStyle.fontWeight: FontWeight.W500
}

There are some ‘textFit’ properties on Labels where you can set min and max font sizes and more. In this case I want to limit the font size for TitleText. The property itself is defined at ListView:

ListView {
    id: trackedList
    // ...
    property bool column2Visible: app.isPassport() || OrientationSupport.orientation == UIOrientation.Landscape
    property int categoryImageSize: app.isPassport()?120:80
    property int imageSize: app.isPassport()?120:81
    property int markerImageSize: app.isPassport()?92:61
    property int titleTextMaxSize: app.isPassport()?11:10
    property int bodyTextMaxSize: app.isPassport()?10:9
    // ...
} // end ListView

As you can see I have different max values for Passport and other devices.

Some rules:

  • At first always design your layout using default font size to get an optimal result
  • Then change font sizes from Settings
  • Try to find a layout design working with all sizes
    • If not find out maximum values

Don’t forget: all of this is HowTo make it work from 10.2 without switching to 10.3 API. Using 10.3 and ‘DU’s’ (Design Units) and asset folders for density / size / … there are more options to do it then from 10.2 where you only can use the 1440×1440 static assets folder to place assets used by passport.

As soon as you’re using multiple QML files with same name  for different devices, density etc. development becomes more difficult. At first you should always try to do your work from one single QML file for a Page, Sheet, Container. Later when your UI is more stable, duplicate the files and do the device-specific layouting. Doing this too early means all changes must me done in multiple files.

Here’s a tip HowTo use functions with some UI Logic from more then one QML File without duplicating the functions itself:

  • Create an extra QML File for a Container
    • This Container only contains functions, no UI Controls
  • Attach this Container to all Pages (per ex. PageXYZ.qml in assets/ and also assets/1440×1440) calling these functions

Then you only have to manage the function from one place.

Here’s the Container containing UI Logic. In this case there are two functions to check if a tracked data item is overlapping start or stop time with already tracked items. Functions are filling a temp GroupDataModel to check this, so it’s also inside the Container – no one else needs it.

I’m placing such Containers inside an extra folder: assets/ui_logic to make it clear that these qml files only contain some logic.

This is assets/ui_logic/CheckOverlappingTimes.qml:

import bb.cascades 1.2

Container {
    id: checkOverlappingTimes
    
    attachedObjects: [
        GroupDataModel {
            // f,t, id
            id: dataModelOverlap
            sortingKeys: [ "f" ]
            sortedAscending: false
            grouping: ItemGrouping.ByFullValue
        }
    ]
    
    function isStartNotOverlapping(start){      
        // your logic
    }
    
    function isStartStopNotOverlapping(uuid, start, stop){
        // your logic
    }
}

Pages calling these functions:

import "ui_logic"
Page {
    id: myPage
    // ...
    attachedObjects: [
        // dummi
        CheckOverlappingTimes {
            id: checkOverlappingTimes
            visible: false
        }
    ]
    // ...
    actions: [
       ActionItem {
            id: saveAction
            title: qsTr("Save")
            ActionBar.placement: ActionBarPlacement.OnBar
            imageSource: "asset:///images/save.png"
            onTriggered: {
                var startStopValid = checkOverlappingTimes.isStartStopNotOverlapping(uuid, startTime, stopTime)
                if(!startStopValid){
                    // do something
                    return
                }
            }
        },    
    ]
    // ...
}

Now all calls to these functions are delegated to our special Container.

Hope you got some ideas where to look in your apps to support Passport Device from your 10.2 API.

Next article will go one step further and use 10.3 API which means you have to support two different APIs – I’ll tell you how I’m doing this.

Have Fun with BlackBerry Passport !

… and don’t forget: See the bigger picture soon in Toronto, London or Dubai.

This article is a follow up of supporting blackberry passport – step one 10.2

While preparing my apps for BlackBerry Passport I notices some “problems” using shortcuts. As a good native-app-citizen I always try to provide shortcuts for users of Q5 / Q10 to ease their workflow.

Upcoming BlackBerry Passport has a much cooler and innovative keyboard: only 3 rows of physical keys plus one or more virtual rows with context-sensitive virtual keys. … will blog about this later in detail.

kbd_q10_pp

As you can see the physical keys are missing the ‘alt’ and ‘shift’ keys. Take a look at Cascades documentation on shortcuts: you’ll see that you can use shortcuts with combinations of ‘alt’ or ‘shift’ and there are some situations where I did this in my TimeTracker app (http://TimeTracker10.org)

Here’s a special screen where I’m using a Segmented TitleBar:

q10_segmented_tb

To switch between the ‘Tabs’ from Segmented TitleBar you have to tap on a Tab, which means you have to move your hand from the keyboard. Using shortcuts you can go on easy. It’s always a challenge to find the right keys working for all your screens in all languages without collision of SystemShortcuts. So I decided to number the Segments and to use the number as Shortcut key. This will be consistent through all languages and looks the same on all Pages with Segmented TitleBars.

For the user it’s easy to understand and to remember:

q10_numbered_keys

To type 1, 2, 3 or 4 you have to type ‘alt w’, ‘alt e’, ‘alt r’ or ‘alt s’. I used a trick to display the numbers:

shortcuts: [
    Shortcut {
        key: "2"
    },
    Shortcut {
        key: qsTr("Alt + e")
    }
]

You can define more then one shortcut for an Actionitem and Cascades will always show the first one. So in this case the ‘2’ will be visible, but to type a ‘2’ in reality the user has to press ‘alt’ and ‘e’.

Now with Passport there’s no ‘alt’ and there are no numbers, so my tricky workaround won’t work on this screen:

passport_segmented_tb

Here’s a possible solution:

shortcuts: [
    Shortcut {
        key: app.isPassport()?qsTr("D"):"2"
    },
    Shortcut {
        key: qsTr("Alt + e")
    }
]

It’s up to you: change all shortcuts or provide different sets for Q5/Q10 vs Passport. Using shortcuts like ‘D’ it’s important to make them translatable – then you can translate them easy without changing the code itself.

Here are the new shortcuts on Passport:

IMG_20140903_130049

BTW: take a look at the screen layout: BlackBerry Passport allows to place big icons to ‘jump’ to other areas. (Users of this app like it to have big buttons)

Remark: I have to redesign the upscaled Icons to make them look better – it’s on the ToDo ;-)

See the bigger picture

Have fun moving your apps forward to BlackBerry Passport !

… and don’t forget: See the bigger picture soon in Toronto, London or Dubai.