Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Developing Mobile Apps, Lecture 5


Published on

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

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Developing Mobile Apps, Lecture 5

  1. 1. Developing webOS Apps CS96SI UI Components and Services Fred Patton Editor-in-chief, Palm Developer Portal Thursday, April 29, 2010 1
  2. 2. 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. Thursday, April 29, 2010 2
  3. 3. 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. Thursday, April 29, 2010 3 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!
  4. 4. 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. Thursday, April 29, 2010 4 The Style Matters and UIWidgets examples come with the SDK. They have lots of examples of using and customizing widgets.
  5. 5. The Humble Button <div x-mojo-element="Button" id="button1"></div> this.attributes = { }; this.model = { }; this.controller.setupWidget("button1", this.attributes, this.model); If we do nothing else, we’ll at least get a button Thursday, April 29, 2010 5 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.
  6. 6. Let’s add a label this.attributes = { }; this.model = { buttonLabel: “Hello” }; this.controller.setupWidget("button1", this.attributes, this.model); Thursday, April 29, 2010 6 You could also put the text in the <div>.
  7. 7. Activity Button this.controller.setupWidget('button-1', this.atts = { type: Mojo.Widget.activityButton }, this.model = { buttonLabel: 'Press me', buttonClass: 'affirmative', disabled: false }); activityButton allows for a spinner affirmative buttonClass makes it green Thursday, April 29, 2010 7 Now, why would you want the button to be green? Well, by itself, you probably wouldn’t. But in combination with a (next slide)....
  8. 8. Negative buttonClass this.controller.setupWidget('button-1', this.atts = { type: Mojo.Widget.activityButton }, this.model = { buttonLabel: 'Press me', buttonClass: 'negative', disabled: false } ); Button text is almost unnecessary now... Thursday, April 29, 2010 8 ...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.
  9. 9. Changing the Model ... this.buttonModel.buttonLabel = "Goodbye"; this.controller.modelChanged(this.buttonModel); ... modelChanged alerts the program that it needs to update the widget(s) associated with the model. Thursday, April 29, 2010 9 Note that if you have multiple widgets associated with the model, then ALL of those widgets will be updated.
  10. 10. CSS by Class .myclass .palm-button { -webkit-border-image: url(../images/button-blue- up.png) 0 16 0 16 stretch stretch; } .myclass .palm-button.selected { -webkit-border-image: url(../images/button-blue- down.png) 0 16 0 16 stretch stretch; } <div x-mojo-element="Button" id="fooButton" class="myclass">Press Me</div> myclass inherits from .palm-button, but gets its image overwritten. Thursday, April 29, 2010 10 See for a nice write-up on border images.
  11. 11. Visualizing Border Image .stylishContent { display: inline-block; border-width: 27px 27px 27px 27px; border-image: url( 27 27 27 27; } <div class="stylishContent">Some stylish content</div> Check out Kevin Decker’s article: Thursday, April 29, 2010 11 The border image itself is divided into zones by use of the offset parameters. The various parts of the image are stretched to fit.
  12. 12. 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. Thursday, April 29, 2010 12
  13. 13. 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. Thursday, April 29, 2010 13
  14. 14. List <div> <div id='MyListContainer'> <div id="my_list" x-mojo-element="List" > </div> </div> Goes in your scene HTML Thursday, April 29, 2010 14
  15. 15. List Container <div class="palm-group"> <div class="palm-group-title"> #{-listTitle} </div> <div class="palm-list"> #{-listElements} </div> </div> 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. Thursday, April 29, 2010 15
  16. 16. List Item Template <div class="palm-row"> #{-word} </div> 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 Thursday, April 29, 2010 16 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.
  17. 17. List Instantiation this.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. Thursday, April 29, 2010 17
  18. 18. Setting up “items” items.push({word: “Scintillating”}; this.listModel.items = items; this.controller.modelChanged(this.listModel); Push data into an array Assign the array to the list model Tell the controller that the model has changed List will be updated Thursday, April 29, 2010 18
  19. 19. 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. Thursday, April 29, 2010 19 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.
  20. 20. Menus Thursday, April 29, 2010 20
  21. 21. App Menu 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); Basic setup instantiation - no HTML needed. Need a command handler (see sample) Thursday, April 29, 2010 21 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.
  22. 22. Global Stylesheets All the global style sheets are available in the SDK: share/refcode/framework/[xxx]/stylesheets Shows what styles are available to override. Thursday, April 29, 2010 22
  23. 23. Services Provide access to core applications, hardware, and low level system functions Application services System services Cloud Services Thursday, April 29, 2010 23 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.
  24. 24. Some examples Accelerometer Alarms GPS System sounds Email Thursday, April 29, 2010 24 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.
  25. 25. System Sounds this.controller.serviceRequest("palm://", { method: "playFeedback", parameters: { name: "dtmf_2" } } ); Plays the DTMF tone for the number 2. System requests each have their own identifier. (Not really a URL.) Thursday, April 29, 2010 25 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.
  26. 26. Send an email this.controller.serviceRequest("palm://com.palm.applicationManager", { method: "open", parameters: { id: "", params: { summary: "Subject line", text: "This is the text of the email.", recipients: [{ type: "email", role: 1, //1:to, 2:cc, 3:bcc value: "", contactDisplay: "Fred Patton" //Required! }] } } }); Thursday, April 29, 2010 26 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.
  27. 27. Accelerometer setup 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); Note “bindAsEventListener” - Makes sure an event is passed. Keeps a reference to the object. Listening for particular events. Thursday, April 29, 2010 27 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.
  28. 28. Accelerometer Response MainAssistant.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"); } Thursday, April 29, 2010 28 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.
  29. 29. Wrap-up Any questions? Thursday, April 29, 2010 29