下载

0下载券

加入VIP
  • 专属下载特权
  • 现金文档折扣购买
  • VIP免费专区
  • 千万文档免费下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 BuildingiPhoneAppswithHTMLCSSandJavaScript-使用HTM…

BuildingiPhoneAppswithHTMLCSSandJavaScript-使用HTML,CSS.doc

BuildingiPhoneAppswithHTMLCSSan…

瓜姐Sandyr8
2019-05-19 0人阅读 举报 0 0 0 暂无简介

简介:本文档为《BuildingiPhoneAppswithHTMLCSSandJavaScript-使用HTML,CSSdoc》,可适用于IT/计算机领域

BuildingiPhoneAppswithHTMLCSSandJavaScript使用HTML,CSStxt我的人生有A面也有B面,你的人生有S面也有B面。失败不可怕,关键看是不是成功他妈。现在的大学生太没素质了!过来拷毛片,居然用剪切!有空学风水去,死后占个好墓也算弥补了生前买不起好房的遗憾。本文由wyqbailey贡献doc文档可能在WAP端浏览体验不佳。建议您优先选择TXT,或下载源文件到本机查看。BuildingiPhoneAppswithHTMLCSSandJavaScript使用HTML,CSS和Javascript构建iPhone应用byJonathanStarkwyqbailey翻译本书英文版在线地址:第一章:启程在开始构建iphone应用之前,我先说说游戏规则。在本章我将界定一些术语,比较两种常见开发方法的长短,并且传授本书中用到的种核心web技术的速成法。WebappsVSNativeappsWebapps对我来说,webapp就是一个针对iphone优化定制的网站。网站的类型和内容无关紧要,从小型商业项目到房贷计算器都可以。Webapp最关键的特性是使用标准的web技术构建用户界面,可以使用url访问,并且针对iphone做过优化定制。Webapp不用安装,不会出现在iTunesAppStore,也不是用ObjectiveC编写的。Nativeapps相反的,nativeapp需要安装,可以操控iphone硬件,使用ObjectiveC编写。Nativeapp最关键的特点是可以在iTunesAppStore中找到它。这点足以吸引全球范围内的软件供应商,我也不例外。各有短长不同的应用有各异的需求,有些应用就非常适合使用web技术开发。了解两种方法的优缺点,有助于我们的开发决策。Nativeapp的优点:数百万iTunesAppStore注册用户,轻轻一点,即可购买你的应用Xcode,InterfaceBuilder和theCocoaTouchframework为你提供了良好的开发环境你可以操控使用所有设备硬件,发挥他们的特性Nativeapp的缺点:你必须付费成为一名Appledeveloper你必须接受Apple的审核你必须使用ObjectiveC开发你只能在Mac上开发你不能及时发布bug修复进展开发周期缓慢,测试周期要受AppStore的元素程序加载时date面板没有任何数据,所以也无从绑定click事件解决办法就是在删除按钮被创建时绑定事件,这就需要在refreshEntries()方法中添加代码:newEntryRowfind('delete')click(function(){找到删除按钮,注册click事件varclickedEntry=$(this)parent()删除按钮的父级元素varclickedEntryId=clickedEntrydata('entryId')得到删除数据的id值deleteEntryById(clickedEntryId)调用deleteEntryById方法删除数据行clickedEntryslideUp()})Javascript专家可能疑惑我为什么不用jquery的live()方法来委派删除按钮事件不幸的是,live()方法在iphone上不工作,因为click不是一个冒泡事件下面的deleteEntryById()方法将从数据库删除指定id的数据行:functiondeleteEntryById(id){dbtransaction(function(transaction){transactionexecuteSql('DELETEFROMentriesWHEREid=',id,,errorHandler)})}和前面的例子一样,创建数据事务,使用executeSql方法,第一个参数是sql语句,第二个是sql语句数据,第个执行成功的回调函数没有指定,第个执行错误回调依然使用前面用过的errorHandler到此,我们有了一点点成就做到这一步我们花了一些精力,但其实代码并是非常多整个kilojs有行代码,如范例:范例:varjQT=$jQTouch({icon:'kilopng',statusBar:'black'})vardb$(document)ready(function(){$('#createEntryform')submit(createEntry)$('#settingsform')submit(saveSettings)$('#settings')bind('pageAnimationStart',loadSettings)$('#dateslia')click(function(){vardayOffset=thisidvardate=newDate()datesetDate(dategetDate()dayOffset)sessionStoragecurrentDate=dategetMonth()''dategetDate()''dategetFullYear()refreshEntries()})varshortName='Kilo'varversion=''vardisplayName='Kilo'varmaxSize=db=openDatabase(shortName,version,displayName,maxSize)dbtransaction(function(transaction){transactionexecuteSql('CREATETABLEIFNOTEXISTSentries''(idINTEGERNOTPRIMARYKEYAUTOINCREMENT,''')})})functionloadSettings(){$('#age')val(localStorageage)$('#budget')val(localStoragebudget)$('#weight')val(localStorageweight)}functionsaveSettings(){localStorageage=$('#age')val()localStoragebudget=$('#budget')val()localStorageweight=$('#weight')val()jQTgoBack()returnfalse}functioncreateEntry(){dateDATENOT,foodTEXTNOT,'caloriesINTEGERNOT)'vardate=sessionStoragecurrentDatevarcalories=$('#calories')val()varfood=$('#food')val()dbtransaction(function(transaction){transactionexecuteSql('INSERTINTOentries(date,calories,food)VALUES(,,)',date,calories,food,function(){refreshEntries()jQTgoBack()},errorHandler)})returnfalse}functionrefreshEntries(){varcurrentDate=sessionStoragecurrentDate$('#dateh')text(currentDate)$('#dateulli:gt()')remove()dbtransaction(function(transaction){transactionexecuteSql('SELECT*FROMentriesWHEREdate=ORDERBYfood',currentDate,function(transaction,result){for(vari=i<resultrowslengthi){varrow=resultrowsitem(i)varnewEntryRow=$('#entryTemplate')clone()newEntryRowremoveAttr('id')newEntryRowremoveAttr('style')newEntryRowdata('entryId',rowid)newEntryRowappendTo('#dateul')newEntryRowfind('label')text(rowfood)newEntryRowfind('calories')text(rowcalories)newEntryRowfind('delete')click(function(){varclickedEntry=$(this)parent()varclickedEntryId=clickedEntrydata('entryId')deleteEntryById(clickedEntryId)clickedEntryslideUp()})}},errorHandler)})}functiondeleteEntryById(id){dbtransaction(function(transaction){transactionexecuteSql('DELETEFROMentriesWHEREid=',id,,errorHandler)})}functionerrorHandler(transaction,error){alert('OopsErrorwas'errormessage'(Code'errorcode')')returntrue}小结在这章,我们学习了两种客户端数据存储,一种是keyvalue方式存储,一种是客户端数据库存储。客户端数据库实际上打开了一扇webapp的大门。现在唯一阻碍我们的应用程序离线运行的就是每次初始化都需要从远程服务器读取html代码及相关资源。我们能不能把这些东西也缓存在设备上呢答案是肯定的,下章继续!第章离线使用HTML的"offlineapplicationcache"特性允许用户离线使用web应用。当用户首次访问该web应用时,浏览器会自动下载和存储所需要的文件(HTML,javascript,css,图片及其他)下次用户再访问该应用时,浏览器会自动识别URL并从本地应用缓存中加载文件,而不是从网络上下载。离线应用的基础知识实现离线应用缓存的最重要组件是存放在web服务器上的manifest文件。下面我会用一个简单例子来说明manifest这个概念。Manifest文件是发送给用户设备的一个纯文本文件,它有一个特殊的contenttype:cachemanifest。这个文件中的内容是用户设备必须下载和保存在本地的文件列表。假设一个web目录中包含如下文件:indexhtmllogojpgscriptsdemojsstylesscreencss这时要让应用程序离线使用,我们创建一个和indexhtml同目录的demomanifest文件,然后在manifest文件中加入如下代码:CACHEMANIFESTindexhtmllogojpgscriptsdemojsstylesscreencss文件路径也可以使用绝对路径,如下:CACHEMANIFEST:wwwexamplecomlogojpg:wwwexamplecomstylesscreencssmanifest文件创建之后,我们在html标签上使用manifest标签来关联该文件:此时,我们的离线应用就绪。下次当用户访问我们的web应用时,页面及相关资源还是从远程服务器上下载。但在后台,manifest中所列的所有文件将会被下载到用户设备中。一旦下载完成,用户刷新页面时,应用将只读取本地文件,此时用户可以断开网络继续使用应用程序了。现在用户可以离线使用我们的应用程序了,但新的问题出现了:用户怎么知道什么时候该更新应用程序呢当用户设备联通网络并访问应用时,浏览器会首先检查本地manifest文件和远程manifest文件时候相同。如果远程manifest文件有变动,浏览器会在后台下载manifest文件中所列的所有文件。本地manifest文件和远程manifest文件的比较是逐字节进行的(包括注释和空白行)。如果下载中途失败(如断网),那么已下载的部分文件会被自动丢弃,上次的完整缓存文件会继续运行。如果下载成功,那么新的本地缓存文件会在程序下次启动时发挥作用。连线资源白名单和应急预案我们也可以强制浏览器一直从网络下载指定的资源,也就是说浏览器不会在本地缓存这些文件,用户在离线状态下无法使用这些文件。要定义仅连线使用的资源白名单,在manifest文件中使用NETWORK即可,语法如下:CACHEMANIFESTindexhtmlscriptsdemojsstylesscreencssNETWORK:logojpg上例中,我将logojpg文件设置为仅连线使用,当用户离线时,该图片处会显示一个图像占位符(如图)当用户在线时,图片将正常显示(如图)图图片在离线状态下显示为一个图像占位符图连线状态下图片显示正常如果你不想让用户在离线时看到一个丑陋的占位符,可以使用FALLBACK关键字来定义一个备用文件作为离线的应急预案,代码如下:CACHEMANIFESTindexhtmlscriptsdemojsstylesscreencssFALLBACK:logojpgofflinejpg这样的话,当用户离线使用时,将看到offlinejpg(图)连线时将看到logojpg(图)。图用户离线时显示备用图片图用户连线时图片正常显示我还可以告诉浏览器为所有放置在images文件夹下的文件使用应急预案,代码如下:CACHEMANIFESTindexhtmlscriptsdemojsstylesscreencssFALLBACK:imagesimagesofflinejpg现在,当用户离线时,他将看到所有的图片都显示为替代图片,连线时则正常显示。如图和:图离线时所有图片都显示为替换图片图连线时显示正常图片是否在应用中使用NETWORK或FALLBACK取决于应用的特性。但必须注意的是,离线应用缓存主要用于在本地存储应用程序,而不是为了减轻远程服务器压力,提高响应速度或者其他考虑。大多数情况下应将所有需要的文件都放进manifest文件。如果你的应用有大量动态内容使你无法确定哪些文件该缓存,那说民这个应用不太适合使用离线缓存,你可以考虑一下其他方法(比如客户端数据库)。创建一个动态的manifest文件现在我们可以将上面说到的离线缓存方法应用在卡路里(Kilo)程序中。Kilo虽然由少量的文件组成,但手工罗列文件列表是个费力不讨好的事,况且一个书写错误可能导致整个manifest文件无法工作。所以我们将创建一个php文件来动态读取程序所需的文件,然后创建manifest列表,php代码如下:<phpheader('ContentType:textcachemanifest')echo"CACHEMANIFESTn"$dir=newRecursiveDirectoryIterator("")foreach(newRecursiveIteratorIterator($dir)as$file){if($file>IsFile()$file!="manifestphp"substr($file>getFilename(),,)!=""){echo$file"n"}}>在浏览器中,这个manifest文件最终是这个样子的:CACHEMANIFESTindexhtmljqtouchjqtouchcssjqtouchjqtouchjsjqtouchjqtouchtransitionsjsjqtouchjqueryjskilocsskilojsthemesappleimgbackButtonpngthemesappleimgblueButtonpngthemesappleimgcancelpngthemesappleimgchevronpngthemesappleimggrayButtonpngthemesappleimglistArrowSelpngthemesappleimglistGrouppngthemesappleimgloadinggifthemesappleimgonoffpngthemesappleimgpinstripespngthemesappleimgselectionpngthemesappleimgthumbpngthemesappleimgtogglepngthemesappleimgtoggleOnpngthemesappleimgtoolbarpngthemesappleimgtoolButtonpngthemesappleimgwhiteButtonpngthemesapplethemecssthemesjqtimgbackbuttonpngthemesjqtimgbackbuttonclickedpngthemesjqtimgbuttonpngthemesjqtimgbuttonclickedpngthemesjqtimgchevronpngthemesjqtimgchevroncirclepngthemesjqtimggrayButtonpngthemesjqtimgloadinggifthemesjqtimgonoffpngthemesjqtimgrowheadpngthemesjqtimgtogglepngthemesjqtimgtoggleOnpngthemesjqtimgtoolbarpngthemesjqtimgwhiteButtonpngthemesjqtthemecss现在打开indexhtml文件,添加manifest引用:现在manifest文件时动态生成的了,不过我们需要再完善一下代码,好让文件夹内容有变化时缓存文件自动更新:<phpheader('ContentType:textcachemanifest')echo"CACHEMANIFESTn"$hashes=""$dir=newRecursiveDirectoryIterator("")foreach(newRecursiveIteratorIterator($dir)as$file){if($file>IsFile()$file!="manifestphp"substr($file>getFilename(),,)!=""){echo$file"n"$hashes=mdfile($file)}}echo"#Hash:"md($hashes)"n">修正之后的manifest文件看起来如下:CACHEMANIFESTindexhtmljqtouchjqtouchcssjqtouchjqtouchjsthemesjqtimgtoolbarpngthemesjqtimgwhiteButtonpngthemesjqtthemecss#Hash:ddafebdacadacfea程序目录内的任意一个文件发生任何变化,manifest文件中的Hash值都会发生变化,这样本地缓存文件就会在程序启动后自动更新。调试调试离线模式的应用程序是件比较困难的事。你会发现你频繁的查看文件是否下载,或者查看远程和本地资源。再者,不停的切换在线和离线模式不是个好办法,会拖慢开发测试和调试周期。有两种办法帮助我们,一是设置一些控制台记录,二是查看应用程序缓存数据库。Javascript控制台将下面这段代码加入到你的应用程序中会让你的开发做到心中有底,事半功倍。这段代码会向控制台反馈情况,且省却你不断的刷新浏览器。缓存状态数组①varcacheStatusValues=cacheStatusValues='uncached'cacheStatusValues='idle'cacheStatusValues='checking'cacheStatusValues='downloading'cacheStatusValues='updateready'cacheStatusValues='obsolete'为所有可能的时间注册监听器②varcache=windowapplicationCachecacheaddEventListener('cached',logEvent,false)cacheaddEventListener('checking',logEvent,false)cacheaddEventListener('downloading',logEvent,false)cacheaddEventListener('error',logEvent,false)cacheaddEventListener('noupdate',logEvent,false)cacheaddEventListener('obsolete',logEvent,false)cacheaddEventListener('progress',logEvent,false)cacheaddEventListener('updateready',logEvent,false)将每个事件记录到控制台functionlogEvent(e){③varonline,status,type,messageonline=(navigatoronLine)'yes':'no'status=cacheStatusValuescachestatustype=etypemessage='online:'onlinemessage=',event:'typemessage=',status:'statusif(type=='error'navigatoronLine){message='(prollyasyntaxerrorinmanifest)'}consolelog(message)④}更新完成后切换到新下载文件windowapplicationCacheaddEventListener('updateready',function(){windowapplicationCacheswapCache()consolelog('swapcachehasbeencalled')},false)每秒检查一下manifest文件是否更新setInterval(function(){cacheupdate()},)①前面这几行定义了cache对象的一组状态,HTML定义了个状态值。我将每个状态值映射为简单的描述文字,以便控制台记录中的记录更加语义化。②为每一个可能的事件注册监听器,每个事件都绑定logEvent方法。③logEvent方法记录了事件类型,在线状态和缓存状态。假设事件类型是error且浏览器在线,则可能是manifest文件的标点有误。④在控制台记录信息桌面版safari可以通过开发者》显示错误控制台查看控制台记录。Iphone用户则可以通过设置》safari》开发者来打开调试模式,打开调试模式后,mobilesafari会在地址栏下方显示一个控制台标题栏(如图),通过它可以查看控制台信息(如图)图打开调试模式的mobilesafari如图mobilesafari控制台如果重载页面且打开控制台,你就会每隔秒看到新消息。我强烈建议你多研究一会这玩意,你会找到感觉。你可以试着改改manifest文件,然后看看控制台发生什么神奇变化。应用缓存数据库只有mac环境下安装了iphone模拟器才能使用该方法调试,暂时不翻译小结本章我们学习了无论在线还是离线都能让用户无缝使用应用程序的方法,这种离线模式不论在mobilesafari还是在桌面版的safariwebclip中都有效。有了这个法宝,我们就可以创建一个和nativeapp一样的全屏,离线可用的应用程序。当然,纯粹的web应用不可避免的受到安全等方面的限制。比如web应用无法使用系统的通讯录,摄像头,辅助设备或者振动反馈之类的。下一章,我们将谈论这一问题以及对我们大有帮助的开源项目PhoneGap。第七章本地化我们的web应用程序现在能实现很多本地应用程序的功能:从主屏幕启动,全屏模式运行,在iPhone本机存储数据,甚至在离线模式下使用。我们还为其打造了精致的外观,且设置了和本地应用程序几乎一致的动画效果来为用户提供反馈和上下文环境。尽管如此,我们还有两件事情无能为力:web应用程序无法使用设备特性和硬件(如地理定位,加速器,声音和振动)也无法提交到iTunesAppStore。本章我们将学习如何使用PhoneGap来跨过这些限制。呵呵,手机上的裂缝(gap),聪颖的名字。PhoneGap简介PhoneGap是由Nitobi创建的一个开源项目,主要目的是在web应用程序和移动设备之间假设一座桥梁。目前支持iPhone,googleAndriod和黑莓系统,对诺基亚和windowsmobile的支持正在开发中。iPhone并不是使用最广泛的移动设备。移动通讯的版图被各类设备,平台和操作系统瓜分的四分五裂。如果你是一个web开发者,你肯定对在数十种操作系统的多种浏览器中调试所带来的痛苦深恶痛绝。而移动设备的境况是数百种,所以我们没有必要针对所有设备开发和调试。感谢Apple,创建和推动了一个提供全功能优越体验浏览器的高品质移动设备市场。随着更多厂商加入这个阵营,我们前面做的工作变得更加有意义。通过创建一个web应用,我们了解了移动应用开发的复杂性。我们有一定的代码基础去扩展到其他平台。当然,不同的设备有各自的特点可能有些不支持多点触摸,有些没有加速器即使拥有同样的特性,对开发者可能有不同的陈述PhoneGap抽取了大多数移动设备都支持的应用接口(APIs),所以开发者可以在不同设备使用相同的代码。你仍然需要使用供应商提供的SDK,但不需要重写你的程序代码。还有一些和PhoneGap目的一样的项目或产品,比如RhoMobile()和TitaniumMobile()。我对这两个东西不熟所以无法做比较,你可以去研究研究,说不定比PhoneGap更适合你。本书打开头就是一本iphone书籍,所以我们目前只关注PhoneGap的iPhone部分。但是你要铭记PhoneGap还可以帮你轻松地将应用迁移到andriod,黑莓以及windowsmobile平台。我们将要开始使用PhoneGap打包iPhone应用,使用iphoneSDK需要一台安装了Xcode的Mac电脑。你可以在注册成为一个apple开发者之后免费下载SDK,也可以访问下载,如图()。下载完成后将文件解压到桌面(如图)。图从GitHub网站下载PhoneGap版的iPhoneSDK图将文件解压到桌面PhoneGap包含一系列特定设备文件(如andriod,iPhone,黑莓,windowsmobile)以及一些有用的文件(图)。我们唯一需要关注的是iPhone目录。图PhoneGap根目录包含一系列移动平台子目录iPhone目录包含一些Xcode工程必须的文件(如图)。这些文件没有任何特别之处,在任何一个Xcode工程中都可以找到。图iPhone目录包含一些Xcode工程的起始文件在iPhone目录中有一个www文件夹,你可以将该文件夹视为web应用程序的根目录。PhoneGap默认在该目录下放了两个示例文件:indexhtml和mastercss。我们不需要这些,可以直接删除这两个文件(如图)。图删除www文件夹的默认文件接下来,将我们前几章开发的的Kilo应用文件全部拷贝到www目录下,不要改变文件结构和命名(如图)。紧接着,在indexhtml文件的标签内插入:在此我们无需将phonegapjs文件拷贝到www目录,当打包应用程序时,Xcode会帮我们料理此事。注意,如果你在indexhtml文件中加入了manifest链接,记得删掉它。因为在使用PhoneGap的同时使用manifest会导致一些行为问题。到此,准备工作基本结束。双击PhoneGapxcodeproj文件打开工程,检查你选定的是最新的iPhone模拟器,然后点击BuildandRun按钮。秒钟后,iPhone模拟器将出现并运行我们的应用程序。应用程序现在在iPhone模拟器中以nativeapp模式运行。但他看起来和我们在第章中的全屏web应用没有区别。其实,应用已经有了重大变化,现在我们可以操控硬件特性了。在做到这点之前,我们需要做一点点清理工作。全屏问题请注意现在我们的应用底部有px的间隙(如图)。jQtouch不认为程序运行在全屏模式下,所以为safari的工具栏预留了位置。jQtouch这样认为有其道理,但我们以本地应用模式运行,则可以控制其全屏。解决该问题很简单,在kilojs文件中加入:if(typeof(PhoneGap)!='undefined'){$('body>*')css({minHeight:'px!important'})}代码中使用typeof来判断PhoneGap对象是否存在。如果代码在PhoneGap中运行,则条件为真。如果以webapp模式运行,则条件为假。当应用在PhoneGap下运行时,body标签的所有子元素全部设定了最小高度为px。!important声明使得刚才的定义有最高的优先级。现在应用填满可整个屏幕(如图):定制应用名称和图标PhoneGap打包的应用程序默认名称都是"PhoneGap",图标都是一个蓝底的梯子图片,如图:图应用的默认名称和图标要修改显示在主屏幕的应用名称,在Xcode中打开PhoneGapxcodeproj,然后找到PhoneGap→Config→Infoplist文件。打开该文件后,你会看到bundledisplayname一项设置为"PhoneGap"(如图),双击"PhoneGap"将其修改为Kilo(如图)。保存文件,点击Build→Clean,然后点击BuildandRun按钮。iPhone模拟器会直接运行Kilo应用,点击模拟器中的主屏幕按键回到主屏幕,可以看到"PhoneGap"已经改为了"Kilo"(如图)。图bundledisplayname项默认设置为PhoneGap图将默认名称修改为Kilo图主屏幕显示修改后的名称接下来需要将默认图标修改为特定图标。此处对图标的要求和前面web应用图标的要求一样,所以可以直接使用前面章节中图标。但是jQtouch中的addGlossToIcon设置在PhoneGap中不会起作用。要想取消图标的默认高光效果,选中ConfigInfoplist文件中的UIPrerenderedIcon项的复选框即可(如果没有该项,你就得自己添加该配置)。PhoneGap默认的应用图标名称为iconpng,位于iphone目录下(如图)。将改文件替换为你自己的图标后(如图,),点击Build→Clean,然后点击BuildandRun按钮,在模拟器中按下home按键回到主屏幕,你就会看到图标已经更新了(如图)。图PhoneGap应用的默认图标图自定义图标图替换默认图标图主屏幕图标已经被更新创建启动界面接下来我们需要创建自定义的启动界面来替换PhoneGap的默认启动界面(如图)。这和我们前面章节提高的内容基本一样。图PhoneGap应用的默认启动界面在webapp模式下,全屏应用的启动界面必须是一个px*px的图像,使用了黑色透明状态栏的应用必须是px*px。在PhoneGap下,启动界面一律都是px*px。PhoneGap的默认启动界面图形是位于iPhone目录下的Defaultpng(如图)。使用你自己的图像替换改文件(如图和图),点击BuildandRun按钮,模拟器中就会显示新的启动界面(如图)。图PhoneGap的默认启动界面图像图自定义启动界面图像图替换默认文件图自定义的启动界面效果将应用安装到iPhone上在下一节,我们就爱你个给kilo应用添加音效,振动,提示和其他特性。其中有些特性无法在iPhone模拟器上测试,所以需要将应用安装到真正的iPhone上以便继续。Apple限定在往iphone上安装应用时,应用、手机和开发者(你自己)三者组合必须是唯一标识的。我们需要将这三个数据组合成一个叫做"provisioningprofile"的文件加入到Xcode中。要生成这个文件,你必须成为iPhone开发会员。然后苹果提供了工具然你生成和安装provisioningprofile文件。我强调以下几点:已经生成的AppIDs无法编辑或者删除,所以你不要随意乱写ID。保持简介的简短精确,过于含糊可能会把你自己搞糊涂,过长则会在显示时被裁掉。保持在个字符左右。填写AppID的描述时,直接填写应用名称吧。填写设备描述时,不要忘了设备类型(iPhone,iPod等)和硬件版本(G,G,G,GS等)。不要填操作系统版本,因为这个信息可以随意更改。填写profile的描述时,将应用和设备的名字组合即可。使用javascript控制iPhone现在是时候来增强我们的应用,使它可以调用硬件特性。PhoneGap通过开放相关的javascript接口实现了这个可能。这意味着我们只需要一段javascript代码就可以让iPhone产生振动,如下:navigatornotificationvibrate()太简单了,不是吗蜂鸣,振动和警示PhoneGap使得蜂鸣,振动和警示方法超级简单,所以我放在一块说。继续前面章节的kilo举例,我们要检查用户增加一个新食物之后卡路里总量是否超标,如果超标则iPhone发出蜂鸣,并且进行振动和提示。将下面这段代码加入kilojs:functioncheckBudget(){varcurrentDate=sessionStoragecurrentDatevardailyBudget=localStoragebudgetdbtransaction(function(transaction){transactionexecuteSql('SELECTSUM(calories)AScurrentTotalFROMentriesWHEREdate=',currentDate,function(transaction,result){varcurrentTotal=resultrowsitem()currentTotalif(currentTotal>dailyBudget){varoverage=currentTotaldailyBudgetvarmessage='Youare'overage'caloriesoveryourdailybudget'Betterstartjogging!'try{navigatornotificationbeep()蜂鸣navigatornotificationvibrate()振动}catch(e){Noequivalentinwebapp}try{navigatornotificationalert(message,'OverBudget','Dang!')信息提示}catch(e){alert(message)}}},errorHandler)})}然后我们在创建新食物(createEntry方法)完成之后的回调函数中调用checkBudget()方法:functioncreateEntry(){vardate=sessionStoragecurrentDatevarcalories=$('#calories')val()varfood=$('#food')val()dbtransaction(function(transaction){transactionexecuteSql('INSERTINTOentries(date,calories,food)VALUES(,,)'date,calories,food,function(){refreshEntries()checkBudget()调用checkBudget方法jQTgoBack()},errorHandler)})returnfalse}修改完成之后,点击Build→Clean,然后点击BuildandRun按钮查看效果。图PhoneGap的beep方法播放的是iPhone目录下的beepwav文件图PhoneGap的alert方法允许设定信息的标题和按钮文字图原生的javascript的alert方法不允许你定制信息标题和按钮文字地理定位我们可以让kilo应用保存添加食品时的地点一旦我们有了这个信息,我们可以在应用界面上增加一个"地点"按钮来调用iphone默认的地图应用并在相应地点做标记第一步是在数据库中添加经度和纬度两个字段。使用下面这段代码替换kilojs中的CREATETABLE语句:dbtransaction(function(transaction){transactionexecuteSql('CREATETABLEIFNOTEXISTSentries''(idINTEGERNOTPRIMARYKEYAUTOINCREMENT,'''')})接下来重写原有的createEntry()方法,使其可以得到当前的地理位置,使用下面代码替换原有的createEntry()方法:functioncreateEntry(){try{使用try捕获异常,因为在非PhoneGap环境下navigatorgeolocation会出错navigatorgeolocationgetCurrentPosition(function(position){获取地理位置成功后的回调函数varlatitude=positioncoordslatitude得到纬度varlongitude=positioncoordslongitude得到经度insertEntry(latitude,longitude)},function(){获取地理位置失败后的回调函数insertEntry()})}catch(e){捕获到异常后执行没有参数的insertEntry方法insertEntry()}returnfalse阻止表单默认行为}dateDATENOT,foodTEXTNOT,'caloriesINTEGERNOT,'longitudeTEXTNOT,latitudeTEXTNOT)'相应的,insertEntry()方法也需要完善一下,代码如下:functioninsertEntry(latitude,longitude){vardate=sessionStoragecurrentDatevarcalories=$('#calories')val()varfood=$('#food')val()dbtransaction(function(transaction){transactionexecuteSql('INSERTINTOentries(date,calories,food,latitude,lo'VALUES(,,,,)',date,calories,food,latitude,longitude,数据插入时增加了经度和纬度数据,如果没有得到则为undefinedfunction(){refreshEntries()checkBudget()jQTgoBack()},errorHandler)})}为了确认kilo应用确实保存了地理位置信息,我们直接将该信息显示在界面上。所以我们加入一个检查模块来做这件事。将下面的代码加入到indexhtml文件的之前:InspectEntryCancelinput的类型设置为tel,输入时调取电话拨号键盘,在此处输入数字比较合适MapLocation接下来,我们会让用户在点击日期面板的任意一条信息的时候,inspectEntry面板将从下滑出。所以我们需要给日期面板上的每个条目添加点击事件,并且保证条目中原有的删除按钮功能不变。修改后的refreshEntries()方法如下:functionrefreshEntries(){varcurrentDate=sessionStoragecurrentDate$('#dateh')text(currentDate)$('#dateulli:gt()')remove()dbtransaction(function(transaction){transactionexecuteSql('SELECT*FROMentriesWHEREdate=ORDERBYfood',currentDate,function(transaction,result){for(vari=i<resultrowslengthi){varrow=resultrowsitem(i)varnewEntryRow=$('#entryTemplate')clone()newEntryRowremoveAttr('id')newEntryRowremoveAttr('style')newEntryRowdata('entryId',rowid)newEntryRowappendTo('#dateul')newEntryRowfind('label')text(rowfood)newEntryRowfind('calories')text(rowcalories)newEntryRowfind('delete')click(function(e){传递当前操作事件的event对象varclickedEntry=$(this)parent()varclickedEntryId=clickedEntrydata('entryId')deleteEntryById(clickedEntryId)clickedEntryslideUp()estopPropagation()防止事件冒泡})newEntryRowclick(entryClickHandler)给条目添加点击事件}},errorHandler)})}然后将entryClickHandler()方法加入kilojs文件中:functionentryClickHandler(e){sessionStorageentryId=$(this)data('entryId')dbtransaction(function(transaction){transactionexecuteSql('SELECT*FROMentriesWHEREid=',sessionStorageentryId,function(transaction,result){varrow=resultrowsitem()得到查询结果varfood=rowfoodvarcalories=rowcaloriesvarlatitude=rowlatitude得到纬度varlongitude=rowlongitude得到经度$('#inspectEntryinputname="food"')val(food)$('#inspectEntryinputname="calories"')val(calories)$('#inspectEntryinputname="latitude"')val(latitude)$('#inspectEntryinputname="longitude"')val(longitude)$('#mapLocation')click(function(){跳转至googlemapdevelope相应位置windowlocation=''food''latitude','longitude})jQTgoTo('#inspectEntry','slideup')显示inspectEntry面板},errorHandler)})}在你再次测试应用之前,先从手机或者模拟器上卸载应用。因为如果同名数据库存在的话,数据库不会更新字段(数据库只会整体创建)。所以最好将程序卸载,然后重新安装,数据库则会整体重新创建。加速传感器接下来,我们让kilo具备一个更炫的功能:晃一晃iPhone,kilo将复制一份最新的食物条目。将下面的代码加入到kilojs中:functiondupeEntryById(entryId){if(entryId==undefined){没有食物条目时的处理alert('Youhavetohaveatleastoneentryinthelisttoshakeadupe')}else{dbtransaction(function(transaction){transactionexecuteSql('INSERTINTOentries(date,food,calories,latitude,longitude)''SELECTdate,food,calories,latitude,longitude''FROMentriesWHEREid=',entryId,插入一份最新的食物信息function(){refreshEntries()成功回调,显示刚才加入的信息},errorHandler)})}}现在还要设定应用合适监听加速感应器。我们设置其在日期面板显示时监听加速感应器,在日期面板隐藏时取消监听,代码如下:$('#date')bind('pageAnimationEnd',function(e,info){if(infodirection=='in'){在date面板切入结束之后,开始监听startWatchingShake()}})$('#date')bind('pageAnimationStart',function(e,info){if(infodirection=='out'){在date面板开始切出时,取消监听stopWatchingShake()}})接下来是startWatchingShake方法和stopWatchingShake方法:functionstartWatchingShake(){varsuccess=function(coords){varmax=晃动阈值,值越大,所需的晃动幅度越大if(Mathabs(coordsx)>max||Mathabs(coordsy)>max||Mathabs(coordsz)>max){任意坐标加速运动超过阈值varentryId=$('#dateulli:last')data('entryId')得到最新食物条目的iddupeEntryById(entryId)复制一份}}varerror=function(){}varoptions={}optionsfrequency=监听频率,单位毫秒sessionStoragewatchId=navigatoraccelerometerwatchAcceleration(successerror,options)调用了accelerometer对象的watchAcceleration方法使用sessionStoragewatchId存储该监听器,后面stopWatchingShake方法要用到}functionstopWatchingShake(){navigatoraccelerometerclearWatch(sessionStoragewatchId)清除制定监听器}到此,我们可以测试效果了。程序运行后,切换到日期面板,确保至少有一条食物信息,然后晃动你的iPhone,你就会看到页面重载并多了一条信息。不幸的是,你可能会看到一个取消当前操作的确认对话框(如图)。要取消这个对话框,让复制信息顺畅进行,我们需要在infoplist文件中设置一下。将UIApplicationSupportsShakeToEdit的值改为flase即可(如图)。图我们要想办法去掉这个弹窗图将UIApplicationSupportsShakeToEdit项的值设为false小结本章学习了如何使用PhoneGap,如何在iPhone上安装应用程序,以及如何使用javascript操控iPhone的硬件特性。下一章,我们将学习如何将web应用打包成可执行文件,一级如何提交到iTunesAppStore

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

评分:

/48

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利