Way back at my first conference, BlackBerry Jam Americas 2012, I heard an interesting statistic: 80% of all apps contain lists. And if you think about it's not that surprising of a statistic considering most of the social network apps (Twitter, Facebook, etc) and everyone's favorite app, CB10, are a list of items. Because of that BlackBerry made sure to have a very good feature for lists, and they do called ListView. So this tutorial will mainly focus on ListView but will have a few other features to make the sample application a bit more full featured.

A bit more back story about this tutorial (feel free to skip this part if you just want to learn coding stuff), I wrote this example app very quickly (given a 2 day deadline) for a friend who lives in Trinidad and Tobago and wanted to show it off at a local developer meet up. So the feed is for a local newspaper there. But since RSS feeds usually follow the same .xml format you should be able to replace the source with any feed of your choosing. Finally, this tutorial may not be the best one to read if you are completely new to Cascades because I skip some explanations for the sake of length. On to the tutorial...

Before we set up our ListView, since we know we are going to use certain imports and libraries let's call those in first. So at the top of the page along with bb.cascades 1.0 we need to import in the data library.

import bb.cascades 1.0 import bb.data 1.0

Then in our .pro file we need the following libraries.

LIBS += -lbbdata -lbbsystem -lscreen

ListView

Now let's set up the ListView.  The basic components are ListItemComponent {} which holds the display of the list items, GroupDataModel {} which sorts the data, and DataSource which is exactly what it sounds like, the source of your data. So that general setup would look something like the following

import bb.cascades 1.0 import bb.data 1.0 Page { id: newsPane Container { ListView { id: myListView dataModel: myDataModel listItemComponents: [ ListItemComponent { type: "header" }, ListItemComponent { type: "item" } ] onTriggered: { } } } attachedObjects: [ GroupDataModel { id: myDataModel }, DataSource { id: myDataSource source: "" query: "" type: DataSourceType.Xml onDataLoaded: { } } ] onCreationCompleted: { myDataSource.load(); } }

Now that we have the framework of our ListView we can start filling in our information. First the The DataSource, we need the source: "" and query: "" and then onDataLoaded: {} we want to clear the list then populate it from our source.

DataSource { id: myDataSource source: "http://newsday.co.tt/rss.xml" query: "/rss/channel/item" type: DataSourceType.Xml onDataLoaded: { myDataModel.clear(); myDataModel.insertList(data) } }

Next the GroupDataModel has sortingKeys which we'll want to sort by date, and the tag in the .xml file is "pubdate"

GroupDataModel { id: myDataModel sortingKeys: [ "pubDate" ] sortedAscending: false grouping: ItemGrouping.ByFullValue }

Finally the display of the actual list. For both the header and item let's use custom compoents (rather than StandardListIem) to exactly control the look of components. In this example I didn't want any "header" to show so the easiest way to have that is to have the header as a Container with a blank Label

ListItemComponent { type: "header" Container { Label { text: "" } } }

Then for the "item" compoenent with a stack of Labels with the article title, date, and description. To help separate the feed items, I've inserted a Divider at the bottom of my custom component.

ListItemComponent { type: "item" // Custom List compoents Container { Label { text: ListItemData.title textStyle.fontWeight: FontWeight.Bold multiline: true } Label { text: ListItemData.pubDate } Label { text: ListItemData.description textStyle.fontSize: FontSize.Small multiline: true } Divider { } } }

Additional Features

A stylized title bar can be added to the top of the page. In this example I use name of the newspaper as the title.

Page { titleBar: TitleBar { title: "Newsday" } ... }

The ListView should now be fully set up, however there will be only the info pulled from the .xml shown. Typically a user expects to be able to click on an item and it brings them to the full article and that can be done using the onTriggered: {} signal and a WebView. The WebView will be added to the attached objects inside of Page. To give the WebView page a full set a features, I have also added a ScollView, and a ProgressIndicator for a loading bar. Additionally for the push/pop navigation to work everything needs to be in a NavigationPane. At this point it is easiest to these all added at once.

import bb.cascades 1.0 import bb.data 1.0 NavigationPane { id: newsPane Page { titleBar: TitleBar { title: "Newsday" } Container { ListView { id: myListView dataModel: myDataModel listItemComponents: [ ListItemComponent { type: "header" Container { ... } }, ListItemComponent { type: "item" // Custom List components Container { ... } } ] onTriggered: { var feedItem = dataModel.data(indexPath); var page = detailsPage.createObject(); page.htmlContent = feedItem.link; newsPane.push(page); } } } } attachedObjects: [ GroupDataModel { id: myDataModel ... }, DataSource { id: myDataSource ... }, ComponentDefinition { id: detailsPage Page { property alias htmlContent: detailsView.url Container { layout: DockLayout { } Container { ScrollView { scrollViewProperties.scrollMode: ScrollMode.Both scrollViewProperties { pinchToZoomEnabled: true maxContentScale: 5 minContentScale: 1 } WebView { id: detailsView settings.zoomToFitEnabled: true settings.activeTextEnabled: true onLoadProgressChanged: { // Update the ProgressBar while loading. progressIndicator.value = loadProgress / 100.0 } onLoadingChanged: { if (loadRequest.status == WebLoadStatus.Started) { // Show the ProgressBar when loading started. progressIndicator.opacity = 1.0 } else if (loadRequest.status == WebLoadStatus.Succeeded) { // Hide the ProgressBar when loading is complete. progressIndicator.opacity = 0.0 } else if (loadRequest.status == WebLoadStatus.Failed) { // If loading failed html = "Check Internet connection?" progressIndicator.opacity = 0.0 } } } } } Container { bottomPadding: 25 horizontalAlignment: HorizontalAlignment.Center verticalAlignment: VerticalAlignment.Bottom ProgressIndicator { id: progressIndicator opacity: 0 } } } } } ] onCreationCompleted: { myDataSource.load(); } }

There are a few more things that can be added/enhanced, such as a more stylized "item" list component, but as I said at the beginning I wrote this sample relatively quickly. This should cover most features that are necessary for an RSS feed as well as uses quite a few other UI elements and design features too... Or just think of it as an RSRSS (Really Simple RSS, haha).

Read more