86
A Mobile Web App for Android in 75 Minutes @ jamespearce

A mobile web app for Android in 75 minutes

Embed Size (px)

DESCRIPTION

AnDevCon II workshop, November 2011

Citation preview

Page 1: A mobile web app for Android in 75 minutes

A Mobile Web Appfor Android

in 75 Minutes@ jamespearce

Page 2: A mobile web app for Android in 75 minutes

Single deviceSedentary userDeclarativeThin client Documents

Multi deviceMobile userImperative

Thick client Applications

*

* or supine, or sedentary, or passive, or...

Page 3: A mobile web app for Android in 75 minutes

A badge for all these waysthe web is changing

Page 4: A mobile web app for Android in 75 minutes

JavaScript

Semantic HTML

CSS Styling & Layout

WebFont Video Audio Graphics

Workers & Parallel

Processing

File SystemsDatabasesApp Caches

Cross-AppMessaging

Device Access

Camera

Location

Contacts

SMS

Orientation

Gyro

Network

HTTP

AJAX

Events

Sockets

SSL

(all the elements of a modern application platform)

Page 5: A mobile web app for Android in 75 minutes

IntroducingSencha Touch

Page 6: A mobile web app for Android in 75 minutes

A JavaScript frameworkfor building

rich mobile appswith web standards

Page 7: A mobile web app for Android in 75 minutes

http://sencha.com/touch

Page 8: A mobile web app for Android in 75 minutes

Components

Lists

Page 9: A mobile web app for Android in 75 minutes

Theming

Page 10: A mobile web app for Android in 75 minutes

Forms

Page 11: A mobile web app for Android in 75 minutes

Scrolling

Page 12: A mobile web app for Android in 75 minutes

Touch Events

Page 13: A mobile web app for Android in 75 minutes

Data access & MVC

Page 14: A mobile web app for Android in 75 minutes

Charts

Page 15: A mobile web app for Android in 75 minutes

Kitchen Sink

http://sencha.com/x/5e

Page 16: A mobile web app for Android in 75 minutes

Sencha Touch 2

Page 17: A mobile web app for Android in 75 minutes

Hello World

Page 18: A mobile web app for Android in 75 minutes

http://sencha.com/x/d5

Page 19: A mobile web app for Android in 75 minutes
Page 20: A mobile web app for Android in 75 minutes

<!DOCTYPE  html><html>    <head>            <title>Hello  World</title>

       <script  src="lib/touch/sencha-­‐touch.js"></script>        <script  src="app/app.js"></script>                <link  href="lib/touch/resources/css/sencha-­‐touch.css"                      rel="stylesheet"  type="text/css"  />        </head>    <body></body></html>

Page 21: A mobile web app for Android in 75 minutes

new  Ext.Application({

       launch:  function()  {

               new  Ext.Panel({                        fullscreen:  true,                        dockedItems:  [{xtype:'toolbar',  title:'My  First  App'}],                        layout:  'fit',                        styleHtmlContent:  true,                        html:  '<h2>Hello  World!</h2>I  did  it!'                });

       }

});

Page 22: A mobile web app for Android in 75 minutes
Page 23: A mobile web app for Android in 75 minutes

Lists

var  list  =  new  Ext.List({        store:  store,        itemTpl:  '{firstName}  {lastName}',        grouped:  true,        indexBar:  true});

Page 24: A mobile web app for Android in 75 minutes

Nested Lists

var  list  =  new  Ext.NestedList({        store:  store,        displayField:  'name',        title:  'My  List',        updateTitleText:  true,        getDetailCard:                function(record,  parent)  {..}});

Page 25: A mobile web app for Android in 75 minutes

Carousels

var  carousel  =  new  Ext.Carousel({        direction:  'horizontal',        indicator:  true,        items:  [                ..        ]});

Page 26: A mobile web app for Android in 75 minutes

Common patterns1

var  list  =  new  Ext.List({        store:  store,        itemTpl:  '{firstName}  {lastName}',        grouped:  true,        indexBar:  true});

var  panel  =  new  Ext.Panel({        fullscreen:  true,        layout:  'fit',        items:  [list]});

Page 27: A mobile web app for Android in 75 minutes

Common patterns2

var  panel  =  new  Ext.Panel({        fullscreen:  true,        layout:  'fit',        items:  [{                xtype:  'list',                store:  store,                itemTpl:  '{firstName}  {lastName}',                grouped:  true,                indexBar:  true        }]});

Page 28: A mobile web app for Android in 75 minutes

A more complex app

Page 29: A mobile web app for Android in 75 minutes

Pre-requisitesSencha Touch SDK:

  http://sencha.com/products/touch/

 Yelp developer API key:  http://www.yelp.com/developers/getting_started/

api_overview

 Install Sass and Compass:  http://sass-lang.com/download.html

http://compass-style.org/install/

Page 30: A mobile web app for Android in 75 minutes

The Valley App

http://jamesgpearce.github.com/ValleyGuidehttp://sencha.com/x/e8

Page 31: A mobile web app for Android in 75 minutes

https://github.com/jamesgpearce/ValleyGuide

Page 32: A mobile web app for Android in 75 minutes

Development sequence

1 Structure the app

2 Layout the UI

3 Model the data

4 Load the list

5 Detail page

6 Add a map

7 Customize theme

Page 33: A mobile web app for Android in 75 minutes

1 Structure the app

Page 34: A mobile web app for Android in 75 minutes

index.html

<!doctype  html><html>        <head>                <title>Valley  Guide</title>        </head>

<body></body></html>

Page 35: A mobile web app for Android in 75 minutes

index.html

<script  src="lib/touch/sencha-­‐touch.js"></script>

<script  src="app/yelp.js"></script><script  src="app/app.js"></script>

<link  href="lib/touch/resources/css/sencha-­‐touch.css"              rel="stylesheet"  type="text/css"  />

Page 36: A mobile web app for Android in 75 minutes

app.jsvar  va  =  new  Ext.Application({

       launch:  function()  {

               this.viewport  =  new  Ext.Panel({

                       layout:  'card',                        fullscreen:  true,                        html:  "Hello  world!"                        });

       }

});

Page 37: A mobile web app for Android in 75 minutes

va.viewport

2 Layout the UI

listCard detailCard

toolbar toolbar

dataList

Page 38: A mobile web app for Android in 75 minutes

The app...var  va  =  new  Ext.Application({        launch:  function()  {

               this.listCard  =  new  Ext.Panel({                        html:  'I  am  the  list'                });

               this.detailCard  =  new  Ext.Panel({                        html:  'I  am  the  detail'                });

               this.viewport  =  new  Ext.Panel({                        layout:  'card',                        fullscreen:  true,                        cardSwitchAnimation:  'slide',                        items:  [this.listCard,  this.detailCard]                });        }});

Page 39: A mobile web app for Android in 75 minutes

listCardthis.listCardToolbar  =  new  Ext.Toolbar({        dock:  'top',        title:  'Valley  Guide'});

this.listCardDataList  =  new  Ext.List({        store:  null,        itemTpl:  ''});

this.listCard  =  new  Ext.Panel({        dockedItems:  [this.listCardToolbar],        items:  [this.listCardDataList],        layout:  'fit'});

Page 40: A mobile web app for Android in 75 minutes

detailCardthis.detailCardToolbar  =  new  Ext.Toolbar({        dock:  'top',        title:  '...'});

this.detailCard  =  new  Ext.Panel({        dockedItems:  [this.detailCardToolbar]});

Page 41: A mobile web app for Android in 75 minutes

3 Model the data

http://api.yelp.com/business_review_search?ywsid=YELP_KEY&term=Restaurants&location=Silicon%20Valley

Page 42: A mobile web app for Android in 75 minutes
Page 43: A mobile web app for Android in 75 minutes

Apigee console

Page 44: A mobile web app for Android in 75 minutes

"businesses":  [        {          "rating_img_url"  :  "http://media4.px.yelpcdn.com/...",          "country_code"  :  "US",          "id"  :  "BHpAlynD9dIGIaQDRqHCTA",          "is_closed"  :  false,          "city"  :  "Nashville",          "mobile_url"  :  "http://mobile.yelp.com/biz/...",          "review_count"  :  50,          "zip"  :  "11231",          "state"  :  "TN",          "latitude"  :  40.675758,          "address1"  :  "253  Conover  St",          "address2"  :  "",          "address3"  :  "",          "phone"  :  "7186258211",          "state_code"  :  "TN",          "categories":  [            ...",          ],          ...

Page 45: A mobile web app for Android in 75 minutes

A data namespacethis.data  =  {};

Page 46: A mobile web app for Android in 75 minutes

The ‘Business’ modelthis.data.Business  =  Ext.regModel('',  {        fields:  [                {name:  "id",  type:  "int"},                {name:  "name",  type:  "string"},                {name:  "latitude",  type:  "string"},                {name:  "longitude",  type:  "string"},                {name:  "address1",  type:  "string"},                {name:  "address2",  type:  "string"},                {name:  "address3",  type:  "string"},                {name:  "phone",  type:  "string"},                {name:  "state_code",  type:  "string"},                {name:  "mobile_url",  type:  "string"},                {name:  "rating_img_url_small",  type:  "string"},                {name:  "photo_url",  type:  "string"},        ]});

Page 47: A mobile web app for Android in 75 minutes

A store of those modelsthis.data.restaurants  =  new  Ext.data.Store({        model:  this.data.Business,        autoLoad:  true,        proxy:  {                type:  'scripttag',                url:  'http://api.yelp.com/business_review_search'  +                        '?ywsid='  +  YELP_KEY  +                        '&term=Restaurant'  +                        '&location=Silicon%20Valley',                reader:  {                        type:  'json',                        root:  'businesses'                }        }});

Page 48: A mobile web app for Android in 75 minutes

4 Load the listthis.listCardDataList  =  new  Ext.List({        store:  this.data.restaurants,        itemTpl:  '{name}'});

Page 49: A mobile web app for Android in 75 minutes

A more interesting templateitemTpl:        '<img  class="photo"  src="{photo_url}"  width="40"  height="40"/>'  +        '{name}<br/>'  +        '<img  src="{rating_img_url_small}"/>&nbsp;'  +        '<small>{address1}</small>'

Page 50: A mobile web app for Android in 75 minutes

Hack the style<style>        .photo  {                float:left;                margin:0  8px  16px  0;                border:1px  solid  #ccc;        }</style>

Page 51: A mobile web app for Android in 75 minutes

Get images resized...

...width="40"  height="40"  />

Page 52: A mobile web app for Android in 75 minutes

...in the cloud

src="http://src.sencha.io/40/{photo_url}"  width="40"  height="40"/>

Page 53: A mobile web app for Android in 75 minutes

5 Detail pagethis.listCardDataList  =  new  Ext.List({        store:  this.data.restaurants,        itemTpl:  ...        listeners:  {                selectionchange:  function  (selectionModel,  records)  {                        if  (records[0])  {                                va.viewport.setActiveItem(va.detailCard);                                va.detailCardToolbar.setTitle(                                        records[0].get('name')                                );                        }                }        }});

Page 54: A mobile web app for Android in 75 minutes

List buttonthis.detailCardToolbar  =  new  Ext.Toolbar({        dock:  'top',        title:  '...',        items:  [{                text:  'List',                handler:  function  ()  {                        va.viewport.setActiveItem(                                va.listCard,                                {type:  'slide',  direction:  'right'}                        );                }        }]});

Page 55: A mobile web app for Android in 75 minutes

Detail templatethis.detailCard  =  new  Ext.Panel({        dockedItems:  [this.detailCardToolbar],        styleHtmlContent:  true,        cls:  'detail',        tpl:  [                '<img  class="photo"  src="{photo_url}"                            width="100"  height="100"/>',                '<h2>{name}</h2>',                '<div  class="info">',                        '{address1}<br/>',                        '<img  src="{rating_img_url_small}"/>',                '</div>',                '<div  class="phone  x-­‐button">',                        '<a  href="tel:{phone}">{phone}</a>',                '</div>',                '<div  class="link  x-­‐button">',                        '<a  href="{mobile_url}">Read  more</a>',                '</div>'        ]});

Page 56: A mobile web app for Android in 75 minutes

A little styling.x-­‐html  h2  {        margin-­‐bottom:0;}.phone,  .link  {        clear:both;        font-­‐weight:bold;        display:block;        text-­‐align:center;        margin-­‐top:8px;}

Page 57: A mobile web app for Android in 75 minutes

6 Add a map

va.viewport

listCard detailTabs

toolbar toolbar

dataList dataListdetailCard

Page 58: A mobile web app for Android in 75 minutes

6 Add a map

va.viewport.setActiveItem(va.detailTabs);

...

this.detailMap  =  new  Ext.Map({});

this.detailTabs  =  new  Ext.TabPanel({        dockedItems:  [this.detailCardToolbar],        items:  [this.detailCard,  this.detailMap]});

va.viewport  =  new  Ext.Panel({        layout:  'card',        fullscreen:  true,        cardSwitchAnimation:  'slide',        items:  [this.listCard,  this.detailTabs]});

Page 59: A mobile web app for Android in 75 minutes

Tab titles

this.detailCard  =  new  Ext.Panel({        ...        title:  'Info'});

this.detailMap  =  new  Ext.Map({        title:  'Map'});

Page 60: A mobile web app for Android in 75 minutes

Google Maps script

<script  type="text/javascript"    src="http://maps.google.com/maps/api/js?sensor=true"></script>

Page 61: A mobile web app for Android in 75 minutes

Update the map locationselectionchange:  function  (selectionModel,  records)  {        ...        var  map  =  va.detailMap.map;

       if  (!map.marker)  {                map.marker  =  new  google.maps.Marker();                map.marker.setMap(map);        }

       map.setCenter(                new  google.maps.LatLng(                        records[0].get('latitude'),                        records[0].get('longitude')                )        );

       map.marker.setPosition(                map.getCenter()        );

Page 62: A mobile web app for Android in 75 minutes

Improve the tab barthis.detailTabs  =  new  Ext.TabPanel({        dockedItems:  [this.detailCardToolbar],        items:  [this.detailCard,  this.detailMap],

       tabBar:  {                ui:  'light',                layout:  {  pack:  'center'  }        }

});

Page 63: A mobile web app for Android in 75 minutes

7 Customize theme

Page 64: A mobile web app for Android in 75 minutes

http://sass-lang.com/

Page 65: A mobile web app for Android in 75 minutes

/* SCSS */

$blue: #3bbfce;$margin: 16px;

.content-navigation { border-color: $blue; color: darken($blue, 9%);}

.border { padding: $margin / 2; margin: $margin / 2; border-color: $blue;}

/* CSS */

.content-navigation { border-color: #3bbfce; color: #2b9eab;}

.border { padding: 8px; margin: 8px; border-color: #3bbfce;}

Variables

Page 66: A mobile web app for Android in 75 minutes

$> sudo gem install compass

http://rubyinstaller.org/

Page 67: A mobile web app for Android in 75 minutes

$> compass -v

Compass 0.11.1 (Antares)Copyright (c) 2008-2011 Chris EppsteinReleased under the MIT License.

$> sass -v

Sass 3.1.1 (Brainy Betty)

Page 68: A mobile web app for Android in 75 minutes

Start by copying sencha-touch.scss

Page 69: A mobile web app for Android in 75 minutes

config.rbdir  =  File.dirname(__FILE__)

load  File.join(dir,  'themes')

#  Compass  configurationssass_path        =  dircss_path          =  direnvironment    =  :productionoutput_style  =  :compressed

#  or  :nested,  :expanded,  :compact

Page 70: A mobile web app for Android in 75 minutes

Compile...$>  cd  theming

$>  compass  compile  valley.scss            create  valley.css

$>  compass  compile  valley.scss            identical  valley.css

[edit  file]$>  compass  compile  valley.scss            overwrite  valley.css

$>  compass  watch  valley.scss            >>>  Change  detected  to:  valley.scss            overwrite  valley.css

Page 71: A mobile web app for Android in 75 minutes

Link...<link  href="theming/valley.css"  rel="stylesheet"            type="text/css"  />

Page 72: A mobile web app for Android in 75 minutes

valley.scss@import  'sencha-­‐touch/default/all';

@include  sencha-­‐panel;@include  sencha-­‐buttons;@include  sencha-­‐sheet;@include  sencha-­‐tabs;@include  sencha-­‐toolbar;@include  sencha-­‐list;@include  sencha-­‐list-­‐pullrefresh;@include  sencha-­‐layout;@include  sencha-­‐loading-­‐spinner;...

Page 73: A mobile web app for Android in 75 minutes

valley.scss$base-­‐color:  #9D9E00;$base-­‐gradient:  none;$include-­‐default-­‐icons:  false;$include-­‐border-­‐radius:  false;

@import  'sencha-­‐touch/default/all';

@include  sencha-­‐panel;@include  sencha-­‐buttons;@include  sencha-­‐sheet;@include  sencha-­‐tabs;@include  sencha-­‐toolbar;@include  sencha-­‐list;@include  sencha-­‐list-­‐pullrefresh;@include  sencha-­‐layout;@include  sencha-­‐loading-­‐spinner;

Page 74: A mobile web app for Android in 75 minutes
Page 75: A mobile web app for Android in 75 minutes

Choose own icons$base-­‐color:  #9D9E00;$include-­‐default-­‐icons:  false;

@import  'sencha-­‐touch/default/all';

@include  sencha-­‐panel;@include  sencha-­‐buttons;...

@include  pictos-­‐iconmask('briefcase1');@include  pictos-­‐iconmask('heart');@include  pictos-­‐iconmask('music1');

Page 76: A mobile web app for Android in 75 minutes

http://dev.sencha.com/deploy/touch/docs/theme/

Page 77: A mobile web app for Android in 75 minutes

Sass is a superset of CSS$base-­‐color:  #9D9E00;$include-­‐default-­‐icons:  false;

@import  'sencha-­‐touch/default/all';...

.photo  {        float:left;        margin:0  8px  16px  0;        border:1px  solid  #ccc;}...

Page 78: A mobile web app for Android in 75 minutes

Done?

Page 79: A mobile web app for Android in 75 minutes

Development sequence

1 Structure the app

2 Layout the UI

3 Model the data

4 Load the list

5 Detail page

6 Add a map

7 Customize theme

Page 80: A mobile web app for Android in 75 minutes

A ‘responsive’ app...

http://sencha.com/x/cv

Page 81: A mobile web app for Android in 75 minutes

And if we’d had time...

Add to home screen - Icon - Splash screen

Hybrid app with device APIs

http://sencha.com/x/cyhttp://sencha.com/x/de

Page 82: A mobile web app for Android in 75 minutes

O!ine app$>  phantomjs  confess.js  http://github/valley/

CACHE  MANIFEST

#  This  manifest  was  created  by  confess.js#                    Time:  Wed  Sep  14  2011  10:14:45  GMT-­‐0700  (PDT)#        User-­‐agent:  Mozilla/5.0  ...

CACHE:app/app.jsapp/yelp.jshttp://cdn.sencha.io/touch/1.1.0/sencha-­‐touch.jshttp://maps.google.com/maps/api/js?sensor=truehttp://maps.gstatic.com/intl/en_us/mapfiles/api-­‐3/6/4/main.jstheming/valley.css

NETWORK:*

http://github.com/jamesgpearce/confess

Page 83: A mobile web app for Android in 75 minutes

O!ine data

Taking Yelp data o!ine

Taking images o!ine - src.sencha.io to generate cross-origin B64

Detecting network connection changes

http://sencha.com/x/df

Page 84: A mobile web app for Android in 75 minutes

Weinre

http://phonegap.github.com/weinre

Page 85: A mobile web app for Android in 75 minutes

Apps vs Web technologybuilt with

Page 86: A mobile web app for Android in 75 minutes

James Pearce @ jamespearce