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; }
6)採集用戶體驗數據
頁面控制在客戶端後就不像在服務端那樣比較容易採集用戶使用情況,這裏我推薦使用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