Hybrid移動應用:用網頁技術提供Native體驗
根據最近的一篇 報告 顯示,HTML是移動應用開發人員使用最多的語言,開發人員對于選擇哪種網頁技術考慮的最主要因素,是代碼的跨平臺便攜性和開發的低成本性。我們常常聽 說,hybrid app使用起來非常慢,而且設計也很糟糕,讓我們看看是否有可能又有原生應用的形,又有我們習慣使用的感。
這篇文章會提供很多關于如何構建良好的hybrid移動應用的線索、代碼片段和經驗。我將會大致介紹一下hybrid移動應用的開發,包括它的優 點和缺點。然后,我會分享一下過去兩年我在開發Hojoki和CatchApp時積累的經驗,這兩個項目都運行在主流的移動平臺,并且是由HTML、 CSS和Javascript建成的。最后,我們會介紹一下打包代碼到原生app的一些比較好的工具。
什么是混合模式移動應用
移動app可以大致被分為三種,native、hybrid和web app。如果使用native app,你可以使用設備和操作系統的所有能力,同時,平臺的性能負荷最小。然而,構建web app可以讓你的代碼跨平臺,使得開發時間和成本大大減少。而hybrid app把這兩者的優點都結合起來,使用一套共同代碼,在許多不同的平臺上部署類似原生的app。
有兩種構建hybrid app的方法:
- Webview app:HTML,CSS和Javascript基礎代碼在一個內部的瀏覽器(叫做WebView)中運行,這個瀏覽器打包在一個原生的app中,一些原生的API可以通過這個包被Javascript獲得,比如 Adobe PhoneGap 和 Trigger.io 。
- 被編譯的hybrid app:用一種語言編寫代碼(如C#或者Javascript),對于每一種支持的平臺都把代碼編譯進原生代碼中,這樣做的結果是,每一個平臺都有一個原生的app,但是在開發過程中少了一些自由空間。可以看一下這些例子, Xamarin , Appcelerator Titanium , Embarcadero FireMonkey 。
這兩種方法都被廣泛使用,存在即合理, 不過今天我們只關注WebView app ,因為WebView app可以讓開發人員平衡他們現有的網頁技術。我們來看一下hybrid app相對于native app和web app的各種優點和缺點。
優點
- 開發人員可以使用現有的網頁技術
- 對于多種平臺使用一套基礎代碼
- 減少開發時間和成本
- 使用響應式網頁設計可以非常簡便的設計出多樣的元素(包括平板)
- 一些設備和操作系統特征的訪問
- 高級的離線特性
- 可見度上升,因為app可以原生發布(通過app store),也可以發布給移動端瀏覽器(通過搜索引擎)
缺點
- 某些特定app的性能問題(那些依賴于復雜的原生功能或者繁重的過渡動畫的app,如3D游戲)
- 為了模擬native app的UI和感官所增加的時間和精力
- 并不完全支持所有的設備和操作系統
- 如果app的體驗并不夠原生化,有被Apple拒絕的風險(比如說一個簡單的網站)
這些缺點比較顯著,不能忽略,它們告訴我們,并不是所有的app都適合混合模式,你需要小心的預計你的目標用戶、他們對平臺的選擇和對app的需求。對于許多app來說,好處都是大于壞處的,比如內容驅動的app。
Hojoki和CatchApp都是內容驅動的app,所以我們一開始覺得它們非常適合混合模式的開發方式。我們之前提到的好處中的前三點對于我 們構建Hojoki的移動app幫助很大,不過也僅僅是4周的時間而已。顯而易見,Hojoki的第一個版本缺失了很多重要的東西,接下來的時間里,我們 都把精力撲在提升性能、對每一個平臺制作自定義的UI和利用不同設備的高級特性上。那個時候積累的那些經驗對于讓app形似并神似native app很重要,下面我會盡可能多的分享一下我的經驗。
那么, 怎么能讓你的app形似并神似一個原生的app呢? 對于一個移動網頁開發人員來說,能夠使用設備和操作系統的能力,能夠打包他們的app,這些都聽上去很棒。然后,如果要用戶相信這是一個native app,那么它就必須長得像并且表現的像。如何完成這一點對于混合模式移動開發人員來說仍然是最大的挑戰之一。
讓你的用戶賓至如歸
雖然我們只寫一套基礎代碼,但這并不意味著多種不同平臺上的感官都要完全一樣,你們用戶根本不在乎什么潛在的跨平臺技術,他們只想要app根據他們的期望來展現,他們想要“賓至如歸”。你的第一步應該是為每一個平臺做設計概覽:
雖然這些概覽并不能完美適應全部的app,但是它們仍然提供了一套非常全面和標準的界面和體驗,每一種平臺的用戶都會希望得到這樣的體驗。
DIY VS. UI框架
如果你一個人實施這些組件、樣式和動畫,這是個很大的挑戰,現在有各種各樣的UI框架來幫助你,從商業( Kendo UI )的到開放( lonic )的,從共同UI( JQuery Mobile 和 Onsen UI )到許多有平臺針對性的UI( Sencha Touch 和 ChocolateChip-UI )。有些能夠很好的提供精確到像素的布局,有些則相對粗糙,這些各式各樣的框架能夠很方便的讓使用者定義一個web app。然而,就我的觀念而言,框架最主要的缺點關乎性能,因為大多數UI框架都盡量“海納百川”,要根據自己的情況在設備上試試demo后再決定是否要 使用。
在制作Hojoki的時候,我們嘗試自己用CSS3和極少的Javascript來創建所有的組件,這樣做的好處是能夠幫助我們控制性能,減少負荷。當然,我們也會使用一些別人使用過的較小的庫來解決一下復雜的任務。
自定義UI組件
自定義UI組件也有很多很好的使用例子,你需要根據你的目標用戶來決定使用平臺的UI還是自定義UI,如果你想要單干,你需要對UX設計有很深的理解,因為之前的那些概覽都是專家們為了迎合他們平臺用戶的需求而制作的。
不管你是決定堅持使用平臺的UI概覽還是自己做自定義的組件,你都必須知道,有一些特定的設計樣式是用戶每天使用并熱愛的。通常我們如何把一個app介紹給用戶呢?通過幻燈片講演或者教學覆蓋。用戶如何導航?如果標簽欄或者 側邊欄 。用戶如何快速加載或者刷新數據?下拉刷新。(在接下來的文章中會講到類似原生的滾動)
移動端UI設計的資源
- “ 移動端UI設計樣式:10幾個靈感迸發的網站 ”,Jacob Gube,Six Revisions
- “ 用HTML、CSS和Javascript克隆IOS 7的UI “,C?me Courteault
- “ 用HTML5點進移動端UI ”(幻燈片),Luke Melia and Yael Sahar, Slideshare
設計一個看起來原生的標題欄
在UI中,標題欄是一個很重要的部分,包括它的標題、導航元素、尤其是前進和后退按鈕。對于我來說,許多流行框架在提供HTML和CSS解決方案方面,相比一些原生的app是失敗的,而為每個平臺用最小的DOM和最少行的css代碼來仿照這個UI部分其實相當的簡單.
html<br /> <header><br /> <button class="back">Feed</button><br /> <h1>Details</h1><br /> <!-- more actions (e.g. a search button on the right side) --><br /> </header>
在JSFiddle中查看“ IOS、Android和Windows Phone中看起來原生的標題欄 ”的完整代碼,下面是我的成果:
用html5和css做成的看起來原生的標題欄
在不同的平臺上使用相同的DOM更為便利,因為代碼整潔而且易于維護,我發現這樣做對于許多IOS和Android上的UI組件都適用(包括標題 欄、標簽欄、定制的導航菜單、設置頁面、浮層,還有很多其他的東西)。然而,想要更多的支持Windows Phone變得更加困難,因為它帶來了許多非常不一樣的設計模塊。
支持高分辨率屏幕
現如今,高分辨率的智能手機和平板構成了巨大的移動設備市場,在 ios設備中占有率超過80% ,在 android設備中占有率超過70% 。為了讓你設備上的圖片展現得更清晰,你通常不得不將其尺寸放大到超過它原本大小的兩倍,因此現在響應式網站設計中,如何針對所有不同的分辨率提供適合尺 寸的圖片,成為了現在熱議的話題之一。現在有非常多的途徑解決,每一種的優點和缺點都與帶寬、代碼易維護性和瀏覽器的兼容性有關,現在讓我們來快速的回顧 一下當下最流行的方法,順序不分先后:
- 服務端的調整和傳輸
- 客戶端通過javascript的檢測和替換
- html5的picture元素
- html5 的srcset屬性
- css image-set屬性
- css media queries
- 可伸縮矢量圖形(SVG)
一直以來,針對響應式圖片都沒有一個完美的方法,這主要還是取決于圖片的類型和它們在app上的展現使用方式。如果是靜態圖片(比如logo和教程圖片),我盡量使用SVG,它們能不費吹灰之力的完美縮放,并且 只要你是Android 3+就能獲得很好的瀏覽器支持 。
當你不能選擇SVG的時候, html5的picture元素和srcset屬性 一定會成為日后前端開發人員的首選。當下,它們最大的不足就是在瀏覽器上的支持太局限,因此他們需要一些插件.
同時, css背景圖片和media queries 是比較可靠的解決方案:
css<br /> /* Normal-resolution CSS */<br /> .logo {<br /> width: 120px;<br /> background: url(logo.png) no-repeat 0 0;<br /> }<br /> /* HD and Retina CSS */<br /> @media<br /> only screen and (-webkit-min-device-pixel-ratio: 1.25),<br /> only screen and ( min--moz-device-pixel-ratio: 1.25),<br /> only screen and ( -o-min-device-pixel-ratio: 1.25/1),<br /> only screen and ( min-device-pixel-ratio: 1.25),<br /> only screen and ( min-resolution: 200dpi),<br /> only screen and ( min-resolution: 1.25dppx) {<br /> .logo {<br /> background: url(logo@2x.png) no-repeat 0 0;<br /> background-size: 120px; /* Equal to normal logo width */<br /> }<br /> }
但是,你的app也許已經包含了許多內容(比如新聞文章),要調整所有的圖片標簽或者用css替代會讓我們筋疲力竭,在這種情況下,服務端解決方案就會是最好的選擇。
從去年開始,越來越多的android系統已經離XXHDPI(超高分辨率)屏幕又進了一步。不論上面提到的哪種方案更適合你的需要,你要記住的是你需要用到三倍于原圖大小的圖片來支持android的最新的設備。
使用系統字體
使用系統字體是一種讓用戶體感到賓至如歸的一種簡單但是重要的方法。
主流平臺上,我比較推薦這些字體樣式:
/* iOS */<br /> font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
/* Android */
font-family: 'RobotoRegular', 'Droid Sans', sans-serif;
/* Windows Phone */
font-family: 'Segoe UI', Segoe, Tahoma, Geneva, sans-serif;
此外,ios7提供了一些有趣的預處理,這些預處理可以自動的設置正確的字體、文字大小和行高,在普通文本中應用 font:-apple-system-body
,在標題中使用 font:-apple-system-headline
,這樣不僅簡化了文字的聲明,而且還提升了 動態類型 (這是Apple系統范圍的字號設置)的可訪問性,你可以在 Thomas Fuchs的文章 中了解到更多關于ios7的字體預處理。
<h2> 一個圖標勝過千言萬語 </h2>
<p> 圖像學在所有主流移動平臺的用戶體驗上是一個重要的部分。相比字體,你一定更愿意使用用戶已知的icon,回顧一下我之前說過的高分辨率屏幕,要確保你的icon的大小是可調節的,將它們作為字體通過css的 <code>@font-face</code> 來實現,瀏覽器會有很好的兼容性支持,你甚至可以通過css改變icon的樣式(比如顏色、陰影和透明度)。以下是我的推薦: </p>
<ol>
<li> 獲取多個平臺的icon字體 <a href="/misc/goto?guid=4958866119302784156" rel="nofollow,noindex">Ionicons</a> 是我們的基本設置,因為它幾乎包含了所有我們需要的東西。除了他們常用的一些icon之外,還包含了ios和android的一些特殊的icon,其余的來源于 <a href="/misc/goto?guid=4958866119422555995" rel="nofollow,noindex">ios</a> 、Android <a href="/misc/goto?guid=4958866119532741680" rel="nofollow,noindex">set 1</a> 和 <a href="/misc/goto?guid=4958866119644245149" rel="nofollow,noindex">set 2</a> 以及 <a href="/misc/goto?guid=4958524096742843601" rel="nofollow,noindex">Windows Phone</a> 的特殊icon字體. </li>
<li> 將它們用icon字體生產器結合起來用不同的icon字體讓我們感覺非常混亂,還會迅速的增加文件大小,這就是我們為什么使用 <a href="/misc/goto?guid=4958830721864621033" rel="nofollow,noindex">Fontello</a> 來結合不同字體、調整代碼和針對每個平臺輸出的原因。這樣的結果就是 <code><span class="icon">s</span></code> 在IOS、Android和Windows Phone中看起來是一個搜索圖標。同時,還可以了解一些其他比較流行的方案,比如 <a href="/misc/goto?guid=4958866119823862815" rel="nofollow,noindex">IcoMoon</a> 和 <a href="/misc/goto?guid=4958537863494370320" rel="nofollow,noindex">Fontastic</a> 。 </li>
</ol>
<p> 在 Windows Phone上,你還可以 <a href="/misc/goto?guid=4958866119967628739" rel="nofollow,noindex">脫離Native</a> <code>font-family: 'Segoe UI Symbol'</code> 。 </p>
<h2> 性能優化 </h2>
<p> 性能經常被認為是hybrid移動app中一個主要的缺陷,尤其當你的app有大量的動畫,包含大量的滾動列表并且需要在舊設備上運行的時候,缺 點會越發的明顯。然而,如果你覺得能夠接受只支持一些比較新的平臺版本(Android 4+,iOS 7+和Windows Phone 8+)的話,那你應該就會看到滿意的效果。最終的問題就在于你在優化DOM和CSS選擇器、書寫高性能的Javascript、減少渲染時間和最少化重排 重繪上花了多少工夫。關于移動網頁性能的文章和教程一大把,以下是我最喜歡的一些: </p>
<div>
<p> “ <a href="/misc/goto?guid=4958866120064258387" rel="nofollow,noindex">成功PhoneGap App的性能和UX考慮因素</a> ”,Andrew Trice </p>
<p> “ <a href="/misc/goto?guid=4958866120158496195" rel="nofollow,noindex">移動:網頁性能</a> ” (幻燈片),Estelle Weyl </p>
<p> “ <a href="/misc/goto?guid=4958866120255755938" rel="nofollow,noindex">書寫快速、內存高效的Javascript</a> ,” Addy Osmani, Smashing Magazine </p>
<p> “ <a href="/misc/goto?guid=4958866120376958497" rel="nofollow,noindex">瀏覽器重排最少化</a> ,” Lindsey Simon, Google Developers </p>
<p> “ <a href="/misc/goto?guid=4958866120497817956" rel="nofollow,noindex">如何讓你的網站在移動設備上運行更快</a> ,” Johan Johansson, Smashing Magazine </p>
</div>
<p> 此外,隨著每天都有新的設備推出,移動硬件和渲染引擎都在以一個非常迅猛的速度提升,開發者能夠做到使iPhone5系列、Android手機與Nexus4和5的純原生App的性能上基本一致。 </p>
<h2> 提升感知速度 </h2>
<p> 構建高效的app是一回事而,讓app感覺上運行很快又是另一回事兒。無論你的app是否需要一些時間來完成某項任務(比如一些復雜的計算或者客戶端和服 務器端的交流),實時反饋對于提供流暢和響應式體驗至關重要。一個比較常用的方法是,在用戶還不需要某些功能的時候推遲加載,對用戶接下來可能進行的操作 作預估和預加載。Instagram有一個著名的例子,當用戶忙于添加標簽和分享的時候, <a href="/misc/goto?guid=4958866120612152914" rel="nofollow,noindex">在后臺上傳圖片</a> 。感知速度和真正的速度是不一樣的,讓我們合理運用它。這里有一些非常簡單的例子: </p>
<h3> 消除觸屏設備上點擊的延遲 </h3>
<p> 觸屏設備中的一個普通Javascript點擊事件,從點擊的最開始到得到響應會有輕微的延遲(大約300毫秒),瀏覽器的這種行為是在判斷用戶是單擊還 是雙擊,如果你不需要“雙擊以放大”特性,你可以安全的消除這300毫秒從而換取更多響應操作,我最喜歡的解決方案是 <a href="/misc/goto?guid=4958538438644315681" rel="nofollow,noindex">FastClick</a> 庫,你可以把它用在除了IE的所有瀏覽器上: </p>
<p> js<br /> if ('ontouchstart' in window) {<br /> window.addEventListener('load', function() {<br /> FastClick.attach(document.body);<br /> }, false);<br /> } </p>
<p> IE10以上比較容易解決,你只需要添加一些css代碼: </p>
<p> css<br /> html {<br /> -ms-touch-action: manipulation; /* IE 10 */<br /> touch-action: manipulation; /* IE 11+ */<br /> } </p>
<h3> 設計點擊狀態的樣式 </h3>
<p> 只要用戶點擊一些可操作的元素(例如按鈕或者鏈接),app檢測到以后應該馬上給他們一些回應。就像在臺式機上表現不錯的css的偽類 <code>:hover</code> ,在移動端你需要換成 <code>:active</code> 或者一些javascript解決方案。我曾經在JSFiddle上比較過三種 <a href="/misc/goto?guid=4958866120738968070" rel="nofollow,noindex">點擊狀態的方案</a> ,你可以根據你的實際情況使用。 </p>
<p> 還有,記得在調整移動端點擊狀態的時候清楚默認點擊高亮的樣式,此外我建議禁用用戶在一些活動的元素上選擇,因為如果用戶不小心點擊按鈕的時間過長,出現的選擇菜單會很煩人。 </p>
<h4> iOS and Android: </h4>
<p> css<br /> button {<br /> outline: 0;<br /> -webkit-tap-highlight-color: rgba(0,0,0,0);<br /> -webkit-tap-highlight-color: transparent;<br /> -webkit-touch-callout: none;<br /> -webkit-user-select: none;<br /> -moz-user-select: none;<br /> -ms-user-select: none;<br /> user-select: none;<br /> } </p>
<h4> Windows Phone 8+: </h4>
<p> html<br /> <meta name="msapplication-tap-highlight" content="no"> </p>
<h3> 提示加載 </h3>
<p> 你的app總是需要一些時間來完成動作,即使只有一秒,所以要考慮添加加載提示,否則用戶就可能認為有時候app卡住了,或者在不應該點擊的時候亂點,甚 至他們可能會亂砸東西并且歸責于你的app。根據我的經驗,移動端瀏覽器運用gif動畫不是一個好方法。一旦CPU上有一個加載項,gif卡住了,那么這 個GIF對用戶的加載提示就完全沒有作用了。我更喜歡 <a href="/misc/goto?guid=4958827679394399699" rel="nofollow,noindex">Spin.js</a> ,因為可以自己配置并且運用簡單,當然,還有一些其他的方法: <a href="/misc/goto?guid=4958866120849026788" rel="nofollow,noindex">javascript解決方案</a> 和 <a href="/misc/goto?guid=4958528122111382187" rel="nofollow,noindex">css加載方案</a> 。 </p>
<p> 一些跨平臺的工具比如PhoneGap和Trigger.io也提供一些原生的加載狀態,對于全屏動畫加載的展現很棒。 </p>
<h2> 正確設置滾動 </h2>
<p> 滾動在許多app中是決定用戶體驗的最重要因素之一,它讓人又愛又恨,因為要實現這一點取決于你應用依賴的滾動細節以及需要手機系統支持。 </p>
<p> 幾乎所有的app都使用了可滾動內容和固定頭部和/或底部。通常有兩個CSS方法來實現: </p>
<ol>
<li> 在 <code>body</code> 上啟用滾動,在header上增加 <code>position: fixed</code> ; </li>
<li> 在 <code>body</code> 上禁用滾動,在內容上增加 <code>overflow: scroll</code> ; </li>
<li> 在 <code>body</code> 上禁用滾動,在內容上增加JavaScript默認滾動。 </li>
</ol>
<p> 雖然第一種方法有一些優點(例如IOS的原生滾動到頂部動作以及簡潔的代碼結構),我強烈推薦第二種方法: <code>overflow: scroll</code> 。這個方法 <a href="/misc/goto?guid=4958866120963723008" rel="nofollow,noindex">渲染問題更少</a> (雖然還是比較多),現代平臺上的瀏覽器支持更好(Android 4+,IOS 5+和Windows Phone 8+),對于低版本瀏覽器有 <a href="/misc/goto?guid=4958866121047420227" rel="nofollow,noindex">方便的小插件</a> 。另外,你可以把 <code>overflow: scroll</code> 換成自定義的滾動庫(第三種選擇),例如 <a href="/misc/goto?guid=4958865927757684572" rel="nofollow,noindex">iScroll</a> 。雖然這些JavaScript解決方案使得特性更加靈活(例如,帶動量效果的滾動位置,事件處理,可定制的效果和滾動條等),但它們通常會影響性能。當你在內容里用了許多DOM節點和/或CSS效果(例如 <code>box-shadow</code> , <code>text-shadow</code> , <code>opacity</code> 和 <code>rgba</code> )時會很危險。 </p>
<p> 讓我們來看一些基本的滾動特性。 </p>
<h3> 動量效果 </h3>
<p> 觸摸友好的動量效果使得用戶在大塊內容區域的快速滾動顯得很直觀。通過一些簡單的CSS就能在IOS 5+以及Android上一些版本的Chrome中激活。在IOS上,這也會使得內容不溢出頂部和底部邊界。 </p>
<p> css<br /> overflow-y: scroll;<br /> -webkit-overflow-scrolling: touch; </p>
<h3> 下拉刷新 </h3>
<p> 網頁上有許多實現這個效果的方法,例如 <a href="/misc/goto?guid=4958866121159538523" rel="nofollow,noindex">Damien Antipa</a> 寫的一種。這個方法在IOS和Windows Phone中效果和體驗很相似,Android最近發布它特有的結構(如下)。我們通過一些JavaScript和CSS keyframes在CatchApp里實現了這個效果。(我還沒有總結好放到Github上,所以還在調整!) </p>
<p> <img width="367" height="162" class="alignCenter" alt="Hybrid移動應用:用網頁技術提供Native體驗" src="https://simg.open-open.com/show/b536b7cd15ddef01680df6ad1550ce7b.jpg" /> </p>
<p> IOS中的下拉刷新。 (圖片屬于: <a href="/misc/goto?guid=4958866121159538523" rel="nofollow,noindex">Damien Antipa</a> ) </p>
<p> <img src="https://simg.open-open.com/show/0cf3ee26c3b05b23dcb9a28cef4f8754.gif" /> </p>
<p> Android中的下拉刷新。 (圖片屬于: <a href="/misc/goto?guid=4958866121250148233" rel="nofollow,noindex">Android Widget Center</a> ) </p>
<p> <img width="367" height="236" class="alignCenter" alt="Hybrid移動應用:用網頁技術提供Native體驗" src="https://simg.open-open.com/show/3399d8a16890d76c98a28285f96348f3.jpg" /> </p>
<p> Windows Phone中的下拉刷新。 (圖片屬于: <a href="/misc/goto?guid=4958866121326974007" rel="nofollow,noindex">David Washington</a> ) </p>
<h3> 滾動回到頂部 </h3>
<p> 不幸的是,在 <code>body</code> 上禁用滾動的同時會破壞IOS中允許用戶通過點擊狀態欄快速回到頁面頂部的原生特性。我寫了一小段可以添加在任何元素上的腳本來使用JavaScript解決 <a href="/misc/goto?guid=4958866121417540123" rel="nofollow,noindex">滾動到頂部的問題</a> ,即便內容當前處于動量效果中。把它添加到手機端網頁頭部或通過原生插件添加到狀態欄上(例如,PhoneGap)。 </p>
<p> 許多其他滾動的特性可以通過原生 <code>overflow: scroll</code> 實現,例如關閉特定元素或只是無限滾動。如果需求更加復雜,一定考慮使用JavaScript方法。 </p>
<h2> 讓點擊更容易 </h2>
<p> 用戶觸摸時,很容易跟目標偏差幾個像素,尤其是點擊小按鈕時(例如IOS頂部條上的按鈕)。開發者可以在保證設計的情況下通過在小目標周圍開啟不可見觸摸區域來使用戶體驗更好。 </p>
<p> html<br /> <button><br /> <div class="innerButton">Click me!</div><br /> </button> </p>
<p> 你需要在按鈕元素上綁定事件處理器,同時用 <code>div.innerButton</code> 定義樣式。在JSFiddle上查看 <a href="/misc/goto?guid=4958866121490924901" rel="nofollow,noindex">完整的,含有CSS</a> 的例子。 </p>
<h2> 使用觸摸手勢 </h2>
<p> 智能手機的精髓就是觸摸和手勢。在和觸摸設備交互時,我們總是滑動,按壓,縮放,拖動和長按。所以,為什么不提供相同的方式來讓用戶控制你的hybird應用呢? <a href="/misc/goto?guid=4958344066752667729" rel="nofollow,noindex">QuoJS</a> 和 <a href="/misc/goto?guid=4958836939228003851" rel="nofollow,noindex">Hammer.js</a> 是廣為人知的支持所有手勢類型的庫。如果你想要更多選擇,看一下Kevin Liew對” <a href="/misc/goto?guid=4958866121625074892" rel="nofollow,noindex">11個多點觸摸和觸摸事件JavaScript庫</a> “的比較。 </p>
<h2> 不要忘了原生功能 </h2>
<p> 用網頁技術構建你的應用并不意味著你不能用原生特性。事實上,所有主要的跨平臺開發工具提供了提供了內置的對重要功能的接口。其中有許多API包括調用設備數據,文件系統,網絡連接,地理位置定位,加速度傳感器,提示(包括推送)等等。 </p>
<p> 通常,你甚至可以通過構建自定義插件來擴展開發工具。在Hojoki,我們加入了許多缺失的特性,包括讀取用戶對于我們app的推送提示的設置,讀取用戶 時區,檢查是否安裝第三方APP并啟動。讓我們來看兩個關于用原生插件實現的效果的例子。首先,讓我們對IOS 6+里的input啟動JavaScript <code>focus()</code> : </p>
<p> js<br /> if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6) {<br /> [YourWebView setKeyboardDisplayRequiresUserAction:NO];<br /> } </p>
<p> 下面是在IOS上把給定字符串復制到設備剪貼板里的代碼: </p>
<p> [[UIPasteboard generalPasteboard] setString:@"Your copied string"]; </p>
<h2> 總要留有出口 </h2>
<p> 網頁開發者經常忽視如何處理hybird應用中的糟糕情況(例如,連接超時,錯誤輸入,時間問題等等)。hybird應用從根本上區別于網站,主 要因為它沒有全局刷新按鈕,在一些移動端操作系統里應用很容易在后臺運行數周。如果用戶死機了,他們唯一的選擇是重啟應用,這勢必要強制退出然后重啟。許 多人甚至不知道怎樣重啟,尤其是在Android 2.x上(它深深隱藏在app設置里)和IOS 6及以下版本上(你需要雙擊home鍵,長按圖標并且關閉它)。 </p>
<p> 所以,在開發中先不要覺得有刷新按鈕就萬事大吉而不考慮出錯的情況,我們應該做的是遇到問題就立即解決。對于其他所有意外的情況,例如包含客戶端 -服務端的通信,準備好應對錯誤情況,給用戶提供一個出口。可以簡單得顯示一個全屏的錯誤信息-“歐!出了些問題。請檢查你的連接并再次嘗試”-下面放一 個大大的“重新載入”按鈕。 </p>
<h2> 如何打包 </h2>
<p> 開發hybrid移動app就需要用到通常開發(移動)網站一樣的工具,開發流程也一樣。雖然這么說,我真正喜歡hybrid的地方是你能比較輕 松地使用HTML、CSSS和JavaScript來部署移動web app。確保對原生特性實現回退,或在完全不支持該特性的情況下找到優雅的解決方案。大多數移動開發者更喜歡讓用戶群留在原生app上,甚至可以向使用移 動網站的用戶宣傳這個app。 </p>
<p> <img width="366" height="650" class="alignCenter" alt="Hybrid移動應用:用網頁技術提供Native體驗" src="https://simg.open-open.com/show/bda5107c70da409106163dd774891be4.jpg" /> </p>
<p> 基于HTML、CSSS和JavaScript的原生WebView打包器 </p>
<p> 那原生部分怎樣呢?移動web app(純的HTML、CSSS和JavaScript)將加載到一個WebView中。作為一個內部瀏覽器引擎,WebView會按照設備的默認瀏覽器 渲染網頁的方式渲染app(可能會存在細微差別——你遇到的情況可能有所不同)。而且,原生“應用開發平臺”用來暴露設備和操作系統的特性,而 JavaScript能通過API調用到這些特性。這個API通常包含有調用特性的接口,比如設備攝像頭、通訊錄、地理位置、文件系統和原生事件(比如通 過Android的硬件按鈕)等特性。 </p>
<p> 有一些跨平臺的開發工具提供了原生應用開發平臺,簡化了整個打包流程。下面深入研究部分工具。 </p>
<h3> PHONEGAP和APACHE CORDOVA </h3>
<p> <a href="/misc/goto?guid=4958199139955699999" rel="nofollow,noindex">PhoneGap</a> 絕對是一個最流行的跨平臺開發工具之一,它的名字本身經常被當作hybrid移動app開發的同義詞。 </p>
<p> 關于它的名字以及與 <a href="/misc/goto?guid=4958866121734740236" rel="nofollow,noindex">Apache Cordova</a> 的關系存在的 <a href="/misc/goto?guid=4958866121815336670" rel="nofollow,noindex">一些誤解</a> 是可以理解的。后者是頂級Apache項目,曾用名就是PhoneGap。它提供了一套設備API,并通過運行在WebView中的HTML、CSSS和 JavaScript調用原生的功能。現在,Adobe PhoneGap是Cordova的一個分支——與Chrome使用Webkit作為其引擎沒有什么不同。 </p>
<p> 兩者都是開源和免費的,支持所有主流平臺,擁有一個開發各類插件和擴展的活躍社區。 </p>
<p> PhoneGap對塑造hybrid貢獻巨大,涌現出的很多新的工具提供了 <strong>附加功能</strong> ,使開發流程簡單。這些工具帶來了很多便利:通過在云端構建app,免去了在本地安裝所有不同平臺的SDK和工具的工作。每個工具都有不同的關注點、平臺支持度和價錢: </p>
<ul>
<li> <a href="/misc/goto?guid=4958521739217138594" rel="nofollow,noindex">PhoneGap Build</a> </li>
<li> <a href="/misc/goto?guid=4958835305670643374" rel="nofollow,noindex">Telerik AppBuilder</a> (前身是Icenium) </li>
<li> <a href="/misc/goto?guid=4958835304262800427" rel="nofollow,noindex">AppGyver Steroids</a> </li>
<li> <a href="/misc/goto?guid=4958535722212098252" rel="nofollow,noindex">Appery.io</a> (前身是Tiggzi) </li>
<li> <a href="/misc/goto?guid=4958866122019285011" rel="nofollow,noindex">Monaca</a> </li>
<li> <a href="/misc/goto?guid=4958866122100085960" rel="nofollow,noindex">Intel XDK</a> </li>
</ul>
<h3> SENCHA TOUCH </h3>
<p> <a href="/misc/goto?guid=4958189732334097104" rel="nofollow,noindex">Sencha Touch</a> 最初是一個針對移動web的UI框架,存在有幾年了。過去,開發者使用Sencha構建app需同時使用其他如PhoneGap這樣的服務來部署成 hybrid app。現在Sencha內置了這種功能,可免費使用。支持的平臺有iOS和Android(都需要通過Sencha自有的原生打包工 具),BlackBerry、Windows 8等更多(通過PhoneGap Build)。 </p>
<h3> TRIGGER.IO </h3>
<p> 在Hojoki,我們在兩年半前開始用 <a href="/misc/goto?guid=4958535722309863575" rel="nofollow,noindex">Trigger.io</a> ,因為當時想找一個比PhoneGap輕量級的替代品。雖然它只支持iOS和Android平臺,但它提供了一套很不錯的原生API、自定義插件和第三方 集成(包括Parse消息推送服務、Flurry分析器以及部分非死book的SDK)。通過Trigger.io的命令行工具,可以將app打包集 成到 <a href="/misc/goto?guid=4958524645657745150" rel="nofollow,noindex">Grunt</a> 的構建過程。如果喜歡自動化,這一點很棒。 </p>
<p> 它的一個重要特性是 <a href="/misc/goto?guid=4958866122245145505" rel="nofollow,noindex">Reload</a> ,該特性能使開發者推送HTML、CSSS和JavaScript的更新到運行中的app。與PhoneGap Build的 <a href="/misc/goto?guid=4958866122330590414" rel="nofollow,noindex">Hydration</a> 不同,Reload專門為開發和生產app設計。這樣就使得合法繞過Apple的提交流程去提交bug解決方案和用A/B測試快速迭代就成為可能。 </p>
<p> 對很多開發者來說,一旦14天的試用期結束,Trigger.io <a href="/misc/goto?guid=4958866122424881146" rel="nofollow,noindex">極高的價格</a> 可能就是它最大的缺點。 </p>
<p> <a href="/misc/goto?guid=4958835305298150462" rel="nofollow,noindex">MoSync</a> 似乎是另一種不與PhoneGap有瓜葛的工具,但不太確定當下它的開發活躍度怎樣。 </p>
<h3> 在真機上測試 </h3>
<p> 顯然,用web技術構建移動app會誘使我們在web瀏覽器上做大部分的測試。在開發非原生特性時還算說得過去,但在發布時一定要避免。提交app之前, 要在盡量多的生產商、平臺和各種機型各種版本上測試。Android的機型和版本太多,在瀏覽器渲染、特性支不支持和生產商更改上會千差萬別。雖然iOS 渲染的差異好很多,但Apple生產的不同尺寸、分辨率和像素密度的設備越來越多。想了解更多請點擊查看“ <a href="/misc/goto?guid=4958866122543921798" rel="nofollow,noindex">設備優先級:測試和響應式web設計</a> ”。 </p>
<p> 在2012年,非死book放棄絕大部分HTML5開發轉向原生開發,其中一個主要原因是“ <a href="/misc/goto?guid=4958866122628555036" rel="nofollow,noindex">缺少調試工具和開發者API</a> ”。半年后, <a href="/misc/goto?guid=4958532312681931803" rel="nofollow,noindex">LinkedIn得出同樣的結論</a> ,聲稱HTML5本身準備好了,但基礎工具和生態系統還沒來得及支持它。從我的角度來說,情況正變得越來越好:Android 4.4+支持WebView的遠程調試;各平臺的開發工具越來越多: </p>
<ul>
<li> “ <a href="/misc/goto?guid=4958866122742831539" rel="nofollow,noindex">Web檢測器</a> ”,Safari(iOS) </li>
<li> “ <a href="/misc/goto?guid=4958866122836485188" rel="nofollow,noindex">使用Chrome在Android上遠程調試</a> ” </li>
<li> “ <a href="/misc/goto?guid=4958866122934741846" rel="nofollow,noindex">在Visual Studio里調試商店app</a> ” (Windows Phone 8.1), Windows Dev Center </li>
<li> <a href="/misc/goto?guid=4958866123018964504" rel="nofollow,noindex">Weinre</a> (針對所有平臺),Patrick Mueller </li>
<li> <a href="/misc/goto?guid=4958544360018289547" rel="nofollow,noindex">Edge Inspect</a> (針對iOS和Android),Adobe </li>
</ul>
<h3> 開始考慮硬發布 </h3>
<p> 為web瀏覽器構建app時,為用戶部署修復程序是簡單的一步,這意味著測試會失去其重要性。當通過app商店發布app,這就需要重新考慮了。把它想成上世紀90年代的軟件開發:你現在就生活在硬發布的世界里。 </p>
<p> 那么,為什么這很糟糕?首先,提交過程隨便就是一兩周(寨見,Apple!)。其次,即使修復程序很快發布,也不能保證用戶在短時間更新app。以下是我的建議: </p>
<ol>
<li> 測試的優先級要高。 </li>
<li> 有類似“強制更新”的邏輯來放棄舊有客戶端版本。 </li>
<li> 使用類似Trigger.io的 <a href="/misc/goto?guid=4958866122245145505" rel="nofollow,noindex">Reload</a> 的機制來修復運行中的代碼。 </li>
<li> 如果想快點,申請 <a href="/misc/goto?guid=4958866123154805184" rel="nofollow,noindex">緊急app審核</a> 。 </li>
</ol>
<h3> 發布到商店 </h3>
<p> 上面提到的工具會為每個平臺生成一個版本,然后將這些版本提交到相應的商店。從這點,過程和發布一個“普通”的原生app幾乎一樣。在這方面,有些已討論過的工具可能有更好的文檔。盡管這樣,以下是官方指南: </p>
<ul>
<li> “ <a href="/misc/goto?guid=4958866123259657572" rel="nofollow,noindex">App分發指南</a> ”,Apple </li>
<li> “ <a href="/misc/goto?guid=4958866123383322127" rel="nofollow,noindex">發布入門手冊</a> ”和“ <a href="/misc/goto?guid=4958866123492718569" rel="nofollow,noindex">發布清單</a> ”,Android開發者 </li>
<li> “ <a href="/misc/goto?guid=4958866123638701624" rel="nofollow,noindex">Windows Phone發布</a> ”,Windows研發中心 </li>
</ul>
<h2> 結論 </h2>
<p> 既然開發的hybrid移動app在Apple的App商店和Google Play已經上線兩年了,這里我就總結下在本文開頭提到的一些優點和缺點。 </p>
<p> 對于我們這樣一個資源有限、沒有原生iOS和Android開發經驗的創業公司,要在短短的幾周內構建一個多平臺的app是不可能的。選擇 hybrid,我們就能復用很多web app的代碼,根據用戶反饋迭代速度就快。我們已經成功發布了支持桌面Windows 8和微軟Surface的原生app,支持Mac OS X的app也使用了基本一樣的代碼。移植到另一個平臺的工作量很大程度上取決于給定瀏覽器與設備的能力和所需要的原生功能的水平高低。我們需要消息推送、 app內置購買、獲取用戶聯系方式,以及其他功能。根據你的需求,很多原生功能會使你很依賴于所選擇的原生打包工具。 </p>
<p> 最后,我們來看看hybrid app是否真的能給出一個原生的感官享受。以下精選了來自app商店的用戶評論。積極和消極的評論都有,其中很多消極的評論來自早期版本——各平臺UI一樣,性能相對較慢。 </p>
<p> 評論略去 </p>
<p> 的確,我們正遠離特定平臺的app開發而面向不斷涌現的很多新技術。去年的Google I/O大會上被問到關于web的未來, <a href="/misc/goto?guid=4958866123757376362" rel="nofollow,noindex">Larry Page說</a> : </p>
<p> 在很長一段時間,我不認為作為開發者的你會考慮是否為這個平臺或那個平臺或其他類似平臺在開發。我認為你應該在更高的層次上工作,你所寫的軟件能在每個平臺運行起來,而且是很容易地運行起來。 </p>
<p> 在這方面,(移動)web取得了很大的成功。使用這個平臺而且仍然能在所有商店分發app是向前邁出的巨大一步。未來會發生什么敬請期待。無論發生什么,使用 <a href="/misc/goto?guid=4958866123866526715" rel="nofollow,noindex">世界上1/3人口</a> (其中超過2/3來自歐洲和美國)依賴的技術大概不會是一個壞的選擇。 </p>
<p> 本文作者:fhz 轉載請注明來自: <a href="/misc/goto?guid=4958866123977166257" rel="nofollow,noindex"> <strong>攜程UED</strong> </a> </p>
</div>
</div>