29
Developing webOS Apps CS96SI UI Components and Services Fred Patton Editor-in-chief, Palm Developer Portal 1 Thursday, April 29, 2010

Developing Mobile Apps, Lecture 5

  • Upload
    fpatton

  • View
    2.452

  • Download
    0

Embed Size (px)

DESCRIPTION

Lecture 5 introduces UI widgets, their instantiation and customization, and services.

Citation preview

Page 1: Developing Mobile Apps, Lecture 5

Developing webOS AppsCS96SI

UI Components and ServicesFred Patton

Editor-in-chief, Palm Developer Portal

1Thursday, April 29, 2010

Page 2: Developing Mobile Apps, Lecture 5

What are UI Components?

Common visual/interactive elements.

Basic designs provided, but customization is allowed.

Implemented through “widget assistants” in .js files.

Behavior encapsulated in widget_controller.js.

2Thursday, April 29, 2010

Page 3: Developing Mobile Apps, Lecture 5

Why Use UI Components?

Common components aid user familiarity - no guessing about functionality.

Written documentation is an admission of failure!

Re-use of existing components greatly speeds development time.

Powerful functionality built-in.

3Thursday, April 29, 2010

For example, if you were developing your app as a straight PDK app, you’d need to re-invent the buttons, text boxes, lists.The List widget encapsulates dragging and dropping, deleting from the list, adding to the list, physics based scrolling models, etc.I’m not crazy about going nuts with customization. Written documentation is an admission of failure!

Page 4: Developing Mobile Apps, Lecture 5

Where are they?

Mojo.Widget - Primary source of UI components. Usually declared in the scene view.

Mojo.FilePicker - Allows navigation to, and selection of files. Not declared in the scene view.

Mojo.Menu - not declared in the scene view. Works above the scene.

4Thursday, April 29, 2010

The Style Matters and UIWidgets examples come with the SDK. They have lots of examples of using and customizing widgets.

Page 5: Developing Mobile Apps, Lecture 5

The Humble Button

If we do nothing else, we’ll at least get a button

<div x-mojo-element="Button" id="button1"></div>

this.attributes = {};this.model = {};this.controller.setupWidget("button1", this.attributes, this.model);

5Thursday, April 29, 2010

We’re going to talk about the button for a little while, because it’s a good introduction to the widget framework, use and customization. We’ll then talk about lists and menus.

This is all that’s required to instantiate a button. You need a bit of HTML in your scene’s HTML file, and a bit of setup code in the assistant’s “setup” function.

Page 6: Developing Mobile Apps, Lecture 5

Let’s add a label

this.attributes = {};this.model = { buttonLabel: “Hello”};this.controller.setupWidget("button1", this.attributes, this.model);

6Thursday, April 29, 2010

You could also put the text in the <div>.

Page 7: Developing Mobile Apps, Lecture 5

Activity Button

activityButton allows for a spinner

affirmative buttonClass makes it green

this.controller.setupWidget('button-1', this.atts = { type: Mojo.Widget.activityButton }, this.model = { buttonLabel: 'Press me', buttonClass: 'affirmative', disabled: false });

7Thursday, April 29, 2010

Now, why would you want the button to be green? Well, by itself, you probably wouldn’t. But in combination with a (next slide)....

Page 8: Developing Mobile Apps, Lecture 5

Negative buttonClass

Button text is almost unnecessary now...

this.controller.setupWidget('button-1', this.atts = { type: Mojo.Widget.activityButton }, this.model = { buttonLabel: 'Press me', buttonClass: 'negative', disabled: false });

8Thursday, April 29, 2010

...negative button, you can give the user a clear choice between doing something constructive and something destructive. Text is of course necessary, because you never know when you have a color-blind user.

Page 9: Developing Mobile Apps, Lecture 5

Changing the Model

modelChanged alerts the program that it needs to update the widget(s) associated with the model.

...this.buttonModel.buttonLabel = "Goodbye";this.controller.modelChanged(this.buttonModel);...

9Thursday, April 29, 2010

Note that if you have multiple widgets associated with the model, then ALL of those widgets will be updated.

Page 10: Developing Mobile Apps, Lecture 5

CSS by Class

myclass inherits from .palm-button, but gets its image overwritten.

.myclass .palm-button { -webkit-border-image: url(../images/button-blue-up.png) 0 16 0 16 stretch stretch; }

<div x-mojo-element="Button" id="fooButton" class="myclass">Press Me</div>

.myclass .palm-button.selected { -webkit-border-image: url(../images/button-blue-down.png) 0 16 0 16 stretch stretch; }

10Thursday, April 29, 2010

See http://www.lrbabe.com/sdoms/borderImage/index.html for a nice write-up on border images.

Page 11: Developing Mobile Apps, Lecture 5

Visualizing Border Image

Check out Kevin Decker’s article: http://www.incaseofstairs.com/2010/04/border-image-generator/

.stylishContent { display: inline-block; border-width: 27px 27px 27px 27px; border-image: url(http://www.w3.org/TR/css3-background/border.png) 27 27 27 27;}

<div class="stylishContent">Some stylish content</div>

11Thursday, April 29, 2010

The border image itself is divided into zones by use of the offset parameters. The various parts of the image are stretched to fit.

Page 12: Developing Mobile Apps, Lecture 5

List Widget

One of the most common widgets, but also most powerful.

Many applications will use the list in some form or other.

Scrolling follows a built-in rubber band physics model.

Very customizable.

12Thursday, April 29, 2010

Page 13: Developing Mobile Apps, Lecture 5

List Components

List <div> - Specifies placement of the list. Lives in your scene HTML.

List container - Template file for the list as a whole. Lives in its own HTML file

List item template - describes what each row will look like. Lives in its own HTML file.

13Thursday, April 29, 2010

Page 14: Developing Mobile Apps, Lecture 5

List <div>

<div id='MyListContainer'> <div id="my_list" x-mojo-element="List" > </div></div>

Goes in your scene HTML

14Thursday, April 29, 2010

Page 15: Developing Mobile Apps, Lecture 5

List Container

For this example, file is called “listcontainer.html”

There’s going to be a title on this list, followed by some number of list elements.

<div class="palm-group"> <div class="palm-group-title"> #{-listTitle} </div> <div class="palm-list"> #{-listElements} </div></div>

15Thursday, April 29, 2010

Page 16: Developing Mobile Apps, Lecture 5

List Item Template

For this example, file is called “listitem.html”.

Minimalist HTML for an individual row. (More complicated one coming up.)

Your code will assign data to “word” in the JavaScript

“-” escapes any HTML

<div class="palm-row"> #{-word}</div>

16Thursday, April 29, 2010

Escaping HTML - for example, if you reply with "Joe > Bob!" and don't “-” it, the “>” would be converted to &gt; which may be bad.... so you have to really think about what you are doing with the data etc.

Page 17: Developing Mobile Apps, Lecture 5

List Instantiationthis.listModel = {listTitle:$L(“My List”), items:this.items}; // Set up the attributes & model for the List widget:this.controller.setupWidget('my_list', { itemTemplate:'lists/list/listitem', listTemplate:'lists/list/listcontainer'}, this.listModel);

Note the references to “listTitle” and “listcontainer”.

“items” will be populated elsewhere, but is an array of objects.

17Thursday, April 29, 2010

Page 18: Developing Mobile Apps, Lecture 5

Setting up “items”

Push data into an array

Assign the array to the list model

Tell the controller that the model has changed

List will be updated

items.push({word: “Scintillating”};

this.listModel.items = items;this.controller.modelChanged(this.listModel);

18Thursday, April 29, 2010

Page 19: Developing Mobile Apps, Lecture 5

Complex List Template<div class="palm-row"> <table border="0" cellpadding="0" cellspacing="0"> <tr> <td width="75px"><img src=#{image} height=48 cell-padding="2px" align="center"></td> <td>#{title}<br />#{price}</td> </tr> </table></div>

“image” gets defined elsewhere as a URL.

19Thursday, April 29, 2010

What’s happening here? Each row in the list is going to be comprised of a little table with two columns. The first column has an image in it, and the second colum has title and price info. Price is on the second line.

Page 20: Developing Mobile Apps, Lecture 5

Menus

20Thursday, April 29, 2010

Page 21: Developing Mobile Apps, Lecture 5

App Menu

Basic setup instantiation - no HTML needed.

Need a command handler (see sample)

var appMenuModel = { items: [Mojo.Menu.editItem, { label: $L("Preferences & Accounts"), command: Mojo.Menu.prefsCmd },... { label: $L("Help"), command: Mojo.Menu.helpCmd }] }; this.controller.setupWidget(Mojo.Menu.appMenu, { omitDefaultItems: true }, appMenuModel);

21Thursday, April 29, 2010

If your app is going to have more than one scene, you should put the command handler in the stage assistant, then instantiate the menu in each scene.

Page 22: Developing Mobile Apps, Lecture 5

Global Stylesheets

All the global style sheets are available in the SDK:

share/refcode/framework/[xxx]/stylesheets

Shows what styles are available to override.

22Thursday, April 29, 2010

Page 23: Developing Mobile Apps, Lecture 5

Services

Provide access to core applications, hardware, and low level system functions

Application services

System services

Cloud Services

23Thursday, April 29, 2010

Application services provide access to core applications, so you can launch a URL through the browser, play audio or video, launch the camera or contact apps, etc.System services provide access to hardware-based services and other low-level functions, like location and the accelerometer.Cloud services provide access to web-based services like Extensible Messaging and Presence Protocol (XMPP) messaging.

Page 24: Developing Mobile Apps, Lecture 5

Some examples

Accelerometer

Alarms

GPS

System sounds

Email

24Thursday, April 29, 2010

Accelerometer - gets X, Y, and Z g-loads at up to 30Hz. Also senses orientation. Alarms - Set one to get an event to fire later. Very useful in applications that spend a lot of time idle.GPS - Get current position data, or track position over time.Email - Like a lot of app launchers; launch the app, but populate fields with a specific value. So, you could bring up a new email with the to, from, subject, and body fields already filled in.

Page 25: Developing Mobile Apps, Lecture 5

System Sounds

Plays the DTMF tone for the number 2.

System requests each have their own identifier. (Not really a URL.)

this.controller.serviceRequest("palm://com.palm.audio/systemsounds", { method: "playFeedback", parameters: { name: "dtmf_2" } });

25Thursday, April 29, 2010

I’m going to show a couple of simple code examples to give you the flavor of service calls, and then we’ll get into a live demo of a service.

Page 26: Developing Mobile Apps, Lecture 5

Send an emailthis.controller.serviceRequest("palm://com.palm.applicationManager", { method: "open", parameters: { id: "com.palm.app.email", params: { summary: "Subject line", text: "This is the text of the email.", recipients: [{ type: "email", role: 1, //1:to, 2:cc, 3:bcc value: "mailto:[email protected]", contactDisplay: "Fred Patton" //Required! }] } }});

26Thursday, April 29, 2010

Here we’re using the URI to launch the email application. We’re just populating the To: address. We could populate the message body too, but it gets messy. Code needs to be readable.

Note this uses the Application Manager to launch email. You can do something similar for apps like Photo, Video.

Page 27: Developing Mobile Apps, Lecture 5

Accelerometer setup

Note “bindAsEventListener” - Makes sure an event is passed. Keeps a reference to the object.

Listening for particular events.

if (this.controller.stageController.setWindowOrientation) { this.controller.stageController.setWindowOrientation("free"); this.controller.stageController.setWindowProperties("fastAccelerometer");}this.handleOrientation = this.handleOrientation.bindAsEventListener(this);Mojo.Event.listen(document, 'orientationchange', this.handleOrientation);this.handleAcceleration = this.handleAcceleration.bindAsEventListener(this);Mojo.Event.listen(document, 'acceleration', this.handleAcceleration);

27Thursday, April 29, 2010

Looking at the HTML, you’ll see that I’ve put in some dummy text. Strictly speaking, this isn’t necessary, but like initializing variables, it makes me feel better. I prefer to see something on the screen. That way, if something goes wrong, I’ll at least know whether the HTML is at fault or not, depending on whether it displays anything.

Note the Mojo.Event.listen. We’re listening for two events simultaneously: orientation change and acceleration. Any time either happens, the bound callback will be called. These events happen 30 times per second.

Page 28: Developing Mobile Apps, Lecture 5

Accelerometer ResponseMainAssistant.prototype.handleAcceleration = function(event){ this.controller.get("accx").update("X = " + event.accelX); this.controller.get("accy").update("Y = " + event.accelY); this.controller.get("accz").update("Z = " + event.accelZ); }

MainAssistant.prototype.handleOrientation = function(event){

var position = ["Flat, face up","Flat, face down", "Upright", "Upside Down", "Pointed left", "Pointed right"] this.controller.get("position").update("Current orientation is: " + position[event.position]); this.controller.get("roll").update("Roll: " + event.roll + " degrees"); this.controller.get("pitch").update("Pitch: " + event.pitch + " degrees");}

28Thursday, April 29, 2010

Note that we’re receiving an event object. The contents of that object depend on the event being fired, so we have to be careful what we bind to. An acceleration event contains values for X, Y, and Z acceleration.

Page 29: Developing Mobile Apps, Lecture 5

Wrap-up

Any questions?

29Thursday, April 29, 2010