Phonegap不管UI这块,并且既然选择HTML5作为技术路线,那么就不能基于各个平台的UI库来开发界面,因此选择一个基于mobile的HTML5 UI框架就显得非常重要了。Phonegap官方网站提供了一个选择列表,基本上涵盖了能够和Phonegap集成并且非常主流的开源框架:http://phonegap.pbworks.com/w/page/36767911/UI%20Development%20on%20PhoneGap
这个Page罗列了各个框架的比较信息,我没有做仔细的技术选型的工作,大致通过接受面的广度筛选出Sencha Touch和Jquery Mobile,然后Sencha(以前叫Ext)之前在桌面浏览器端给我留下了不太好的印象(主要是性能方面),所以我就选择了Jquery Mobile,但这里我需要强调的是,我只是选择一种而已,不确定Jquery Mobile就是最好的。
做UI不像做后台架构,主要就是一些细小经验的积累,用过Jquery Mobile一两个月后,有如下的点值得总结:
- 页面流转模式
- page生命周期
- 自动完成组件
- 基于不同大小的Screen动态适配样式
- 统一字体显示
- 采集用户体验数据
- Mobile UI设计的最佳实践
1)页面流转模式
基于Phonegap实际上是用B/S的技术基于C/S的模式来开发,因此页面流转和传统的会有差别。JQM(JQuery Mobile简称)的官方demo是采用传统的B/S模式,页面与页面之间都是通过服务器端来跳转,并且每个page都是独立的html。这对于Phonegap的离线模式来说就不适用了,应用里的所有html都不是从服务器端下载下来执行,而是存放在mobile端本地。这样一来页面流转和业务流程就很自然地放在客户端来开发和执行,因此对于这种方式上的改变,我采取以下两种方案:
- 主要业务逻辑和流程的开发基于JS完成,Server端只是提供相关数据处理的支持,Mobile端与Server端通过Ajax和Websocket来通信,page间通过$.mobile.changePage( "xxx", { transition: "xxx"} );来流转
- page与html文件是多对一的关系,多个page公用一个html可以简化多个page间传值的方便,如果multi-page来开发,可以参考官方文档:http://jquerymobile.com/test/docs/pages/multipage-template.html。在我开发的应用里,由于涉及的page不多(大概20个左右),所以我都放在一个html里,page与page之间通过$.mobile.changePage( "#pageId", { transition: "xxx"} );来流转
2)page生命周期
JQM自己有一套针对各个page生命周期的事件机制,结合JQuery本身的document ready,我拟了一下从一个page的加载并跳转到另外一个page的几个主要事件的状态图(两个page在同一个html里):
如果想深入研究某个事件的具体上下文,可以通过firebug等类似的JS Debug工具,从断点堆栈中来看整个调用流程,直接看源码是很难理清楚事件侦听的过程:
值得注意的是Phonegap的deviceready事件,它是在Phonegap各个组件ready情况下触发,一般说来应该是在jquery document ready之后,但这两者之间没有必然的先后顺序依赖,所以如果需要有两者都ready的情况下才能触发的逻辑,可以采用以下方案:
- var jqReady = $.Deferred(),pgReady = $.Deferred();
- // jq page is ready
- $(document).bind("ready", jqReady.resolve);
- // phonegap ready
- document.addEventListener("deviceready", pgReady.resolve, false);
- // all ready
- $.when(jqReady, pgReady).then(function () {
- console.log("jq and phonegap all ready");
- });
3)自动完成组件
有个第三方组件比较好的提供了JQM自动完成输入的特性,https://github.com/commadelimited/autoComplete.js,doc和demo都非常简单明了,不多说了,我已在各个平台做过测试,非常不错,并且能很好的解决列表过长所带来的性能问题
4)基于不同大小的Screen动态适配样式
跨平台UI开发就需要覆盖各种不同大小screen的device,并且需要采用不同的css,这里不太可能为了screen做不同的package,需要在一个package里自动适配相应的样式,这里可以用到"media",废话不多说,直接看samples:
- #sidebar ul li a {
- color: #900;
- text-decoration: none;
- padding: 3px 0;
- display: block;
- }
- @media all and (min-width: 1001px) {
- #sidebar ul li a:after {
- content: " (" attr(data-email) ")";
- font-size: 11px;
- font-style: italic;
- color: #666;
- }
- }
- @media all and (max-width: 1000px) and (min-width: 700px) {
- #sidebar ul li a:before {
- content: "Email: ";
- font-style: italic;
- color: #666;
- }
- }
- @media all and (max-width: 699px) and (min-width: 520px), (min-width: 1151px) {
- #sidebar ul li a {
- padding-left: 21px;
- background: url(../images/email.png) left center no-repeat;
- }
- }
这样同样的页面在不同screen里分别用不同的样式:
5)统一字体显示
为了在所有平台上都能很高效地统一显示字体,可以采用@Font-face。方法就是把字体文件放到项目package里,然后通过@Font-face加载字体,samples如下所示:
- @font-face {
- font-family: 'blok-regular';
- src: url('type/Blokletters-Potlood.eot');
- src: local('Blokletters Potlood Potlood'),
- local('Blokletters-Potlood'),
- url('type/Blokletters-Potlood.ttf') format('truetype');
- }
- @font-face {
- font-family: 'blok-italic';
- src: url('type/Blokletters-Balpen.eot');
- src: local('Blokletters Balpen Balpen'),
- local('Blokletters-Balpen'),
- url('type/Blokletters-Balpen.ttf') format('truetype');
- }
- @font-face {
- font-family: 'blok-heavy';
- src: url('type/Blokletters-Viltstift.eot');
- src: local('Blokletters Viltstift Viltstift'),
- local('Blokletters-Viltstift'),
- url('type/Blokletters-Viltstift.ttf') format('truetype');
- }
- h1 { font-family: blok-heavy, helvetica, arial; }
页面控制在客户端后就不像在服务端那样比较容易采集用户使用情况,这里我推荐使用google-analytics,使用方法也非常简单,可以参考http://www.google.com/analytics/,主要是以下几步:
- 载入google-analytics lib
- <script type="text/javascript">
- var _gaq = _gaq || [];
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
- </script>
- 绑定相关事件,收集数据
- $('[data-role=page]').live('pageshow', function (event, ui) {
- try {
- _gaq.push(['_setAccount', 'YOUR_GA_ID']);
- hash = location.hash;
- if (hash) {
- _gaq.push(['_trackPageview', hash.substr(1)]);
- } else {
- _gaq.push(['_trackPageview']);
- }
- } catch(err) {
- }
- });
- 查看统计数据
7)Mobile UI设计的最佳实践
Mobile UI设计与桌面程序或网页有很大不同,需要多学习一些最佳实践,这里我推荐两个非常好的资源:
- Apple HIG: http://developer.apple.com/library/ios/#DOCUMENTATION/UserExperience/Conceptual/MobileHIG/Introduction/Introduction.html
- Google IO