(轉)webapp相容移動端的螢幕適配
親測可用!!!!
螢幕適配終極方案
<meta name="viewport" content="width=你的基準畫素, user-scalable=no" />
主要就是這句話,載入header中,底下是原文
本文中所指Mobile WebApp是指執行在Mobile WebKit瀏覽器上的WebApp。本篇文章講解如何像傳統PC網頁開發一樣,使用定寬佈局開發WebApp,並讓WebApp適應多終端裝置:
- 不使用Mobile UI框架
- 不使用響應式佈局
- 適配多終端,適配WebApp佈局寬度為終端裝置解析度寬度
- 一套CSS程式碼,一套佈局方案
- 可以實現複雜的UI介面
- 支援iPhone、Android
閒扯
目前主流的WebApp UI開發框架有jQuery Mobile、Sencha Touch等,這些框架在處理不同裝置解析度的適配時,採用響應式佈局和基於百分比的形式顯示UI元件,UI可以根據裝置的不同尺寸進行呈現。
雖然jQuery Mobile等框架很強大,但是在開發UI複雜的介面時,還是力不從心:百分比設定寬度不能適應複雜的佈局要求。這時就需要固定寬度佈局的開發方式了,但是網上的資料都在講述“定寬網頁設計,並不適用於多終端相容的情況”,jQuery Mobile等框架也沒有提供良好的解決方案,固定寬度佈局在移動裝置上真的不可行嗎?
如果真的不可行,我也不需要寫這篇文章了,哈哈。。。(不要扔板磚,下面進入正題)。。。
一、iPhone、Android自帶瀏覽器如何顯示定寬佈局頁面
viewport是網頁可繪製的區域。雖然viewport可視面積和螢幕尺寸相匹配,但viewport有其自己的尺寸,確定網頁的畫素數量。也就是說,網頁的畫素數量超過定義的viewport尺寸,而不是裝置螢幕尺寸的螢幕面積。例如,雖然裝置螢幕上可能是480畫素寬,viewport是800畫素寬,這時網頁設計定寬800畫素的頁面可以正好完全顯示在螢幕上。
例如下面的程式碼片斷,為HTML文件指定viewport屬性。viewport的寬度為匹配裝置螢幕的寬度,且禁用縮放。
<head> <title>WebApp</title> <meta name="viewport" content="width=device-width, user-scalable=no" /> </head>
iPhone 和 Android 平臺上,WebKit 核心的瀏覽器使用 980 畫素寬的視見區或邏輯尺寸,相當於viewport的width=980px。當頁面載入後,內容通常被完全縮放以便整個頁面都可見,儘管內容會被縮放得非常小,甚至不可讀。下面使用一個簡單的定寬佈局頁面,在部分手機裡使用自帶瀏覽器訪問,顯示情況如下:
可以看到,部分手機中頁面會縮得很小,另外的手機中,頁面被放大,出現橫向滾動條。無論哪種形式,都影響使用者的使用體驗。
二、如何讓定寬佈局的WebApp在iPhone、Android自帶瀏覽器中,自適配終端,完美顯示
iPhone3GS及以上裝置的Safari支援修改viewport的width來改變頁面的縮放情況,你可以將width指定為頁面設計的寬度,如此一來,你的頁面正好充滿viewport並全屏顯示,而不會縮放。如當頁面設計寬度為480px時,可以設定viewport的width=480px:
<meta name="viewport" content="width=480px, user-scalable=no" />
遺憾的是Android4.0以下的手機系統自帶瀏覽器中,不支援設定viewport的width,沒關係,Android自帶瀏覽器支援設定另一引數target-densitydpi來達成目的。經過測試,不同解析度的手機上,如下值可以讓定寬頁面設計的網頁正好填充全屏寬度,而沒有滾動條:
手機 |
解析度寬度 |
佈局寬度480px |
佈局寬度640px |
devicePixelRatio |
HTC Wildfire(G8) |
240px |
240dpi |
320dpi |
0.75 |
HTC Hero(G3) |
320px |
240dpi |
320dpi |
1 |
GT-I9100G |
480px |
240dpi |
320dpi |
1.5 |
Nexus S |
480px |
240dpi |
320dpi |
1.5 |
MT-870 |
540px |
213dpi |
284dpi |
1.5 |
MX032 |
640px |
240dpi |
320dpi |
1.5 |
note2 |
720px |
213dpi |
284dpi |
2 |
I9308 |
720px |
213dpi |
284dpi |
2 |
GT-N7108 |
720px |
213dpi |
284dpi |
2 |
GT-I9228 |
800px |
192dpi |
256dpi |
2 |
從這一庹資料中,會不會有一個放之眾Android機而皆準的公式呢?
各位願意偷懶的不用自己推了,就死我的腦細胞就可以了,就是下方這一條了:
target-densitydpi = UI-width / device-width * window.devicePixelRatio * 160;
//UI-width :WebApp佈局寬度
//device-width :螢幕解析度寬度
其實在上面的一庹資料中,note2和GT-I9228的target-densitydpi 是在得出公式計算出來,並驗證了的。
將Android的處理方式應用到剛才的頁面,在上圖中的手機中訪問以作測試:
觀察上圖可見,在所測試的手機上,測試頁面均自適配到手機螢幕的解析度,全屏顯示且無橫向滾動條。
三、固定寬度佈局WebApp多終端自適配方法總結
1、iPhone上,指定viewport 的width等於頁面設計寬度:
<meta name="viewport" content="target-densitydpi=device-dpi, width=480px, user-scalable=no" />
2、Android上,根據公式計算得出target-densitydpi的值,指定到viewport:
get-target-densitydpi = UI-width / device-width * window.devicePixelRatio * 160; //UI-width :WebApp佈局寬度 //device-width :螢幕解析度寬度
<meta name="viewport" content="target-densitydpi=get-target-densitydpi, width=device-width, user-scalable=no" />
後記
到了這一步就簡單了,寫一個函式針對平臺設定不同的viewport屬性,只需接收網頁設計寬度即可完成設定。
不過在部分手機上,screen.width值不不一定等於螢幕解析度,如三星 I9100G。該如何處理,等總結完成後寫到新一篇裡。。。
補充:自適應指令碼和測試Demo
補充:之前因為程式碼未整理和詳細測試,未能貼出來,以至於很多童鞋在評論區留言希望傳送程式碼,在此表示抱歉。終於下定決心整理了一遍,並經erldy童鞋測試,應無大問題了,現貼出來,方便大家使用。如有問題和意見,請留言。這裡對erldy童鞋的建議和測試表示感謝。
程式碼如下:
/* * 使用說明: * 本程式以完成固定寬度佈局的網頁在iPhone/Android裝置上瀏覽時可以適配裝置螢幕寬度(豎屏瀏覽, 暫未支援橫屏瀏覽) * 為目的。正常執行的環境是: iPhone/Android裝置的自帶瀏覽器. * 如有問題,意見或建議,請到我的部落格頁面留言,或傳送郵件. * 其他移動版瀏覽器的適配問題, 不在本程式處理範圍, 若有相關問題, 請留言或傳送郵件. * * 部落格頁面地址: * http://www.cnblogs.com/plums/archive/2013/01/10/WebApp-fixed-width-layout-of-multi-terminal-adapter-since.html * 郵箱: [email protected] * * 在引入本程式後,請執行如下兩步操作: * 1、對於js不能夠正確獲取到螢幕寬度的裝置, 請使用 * adaptUILayout.regulateScreen.add(裝置name, 裝置userAgent字串標示或正則, { * width : 裝置width, * height : 裝置height * }); * * //Example: * adaptUILayout.regulateScreen.add('三星 I9100G', 'GT-I9100G', { * width : 480, * height : 800 * }); * 錄入裝置螢幕尺寸, 以便程式可以正確的處理適配. * 也可以將已知裝置的尺寸都錄入程式. * * ### 對於如上資料, 大家也可以到我的部落格頁面留言板塊貼出來與大家分享, * 我會收集並新增到程式中去, 以互相幫助, 減少大家的整體工作量. 謝謝! * * 2、使用如下程式碼啟動適配 * adaptUILayout.adapt(佈局寬度); * * Example: * adaptUILayout.adapt(480); * */ var adaptUILayout = (function(){ //根據校正appVersion或userAgent校正螢幕解析度寬度值 var regulateScreen = (function(){ var cache = {}; //預設尺寸 var defSize = { width : window.screen.width, height : window.screen.height }; var ver = window.navigator.appVersion; var _ = null; var check = function(key){ return key.constructor == String ? ver.indexOf(key) > -1 : ver.test(key); }; var add = function(name, key, size){ if(name && key) cache[name] = { key : key, size : size }; }; var del = function(name){ if(cache[name]) delete cache[name]; }; var cal = function(){ if(_ != null) return _; for(var name in cache){ if(check(cache[name].key)){ _ = cache[name].size; break; } } if(_ == null) _ = defSize; return _; }; return { add : add, del : del, cal : cal }; })(); //實現縮放 var adapt = function(uiWidth){ var deviceWidth, devicePixelRatio, targetDensitydpi, //meta, initialContent, head, viewport, ua; ua = navigator.userAgent.toLowerCase(); //whether it is the iPhone or iPad isiOS = ua.indexOf('ipad') > -1 || ua.indexOf('iphone') > -1; //獲取裝置資訊,並矯正引數值 devicePixelRatio = window.devicePixelRatio; deviceWidth = regulateScreen.cal().width; //獲取最終dpi targetDensitydpi = uiWidth / deviceWidth * devicePixelRatio * 160; //use viewport width attribute on the iPhone or iPad device //use viewport target-densitydpi attribute on the Android device initialContent = isiOS ? 'target-densitydpi=device-dpi, width=' + uiWidth + 'px, user-scalable=no' : 'target-densitydpi=' + targetDensitydpi + ', width=device-width, user-scalable=no'; //add a new meta node of viewport in head node head = document.getElementsByTagName('head'); viewport = document.createElement('meta'); viewport.name = 'viewport'; viewport.content = initialContent; head.length > 0 && head[head.length - 1].appendChild(viewport); }; return { regulateScreen : regulateScreen, adapt : adapt }; })();
測試程式碼:
<!doctype html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" /> <style> html, body, h2, div { margin : 0; padding : 0; } body { background : #F7F7F7; } .download { float : left; width : 480px; } .download h2 { margin : 10px; font-size: 30px; background: rgba(0, 0, 0, .1); line-height: 50px; text-indent: 0.2em; } .projectList li { font-size : 30px; line-height : 50px; } </style> </head> <body> <div class="download"> <h2 event="call-test-fn">my WebApp : width 480px</h2> <ul class="projectList"> <li><a href="#">粑粑拉</a></li> <li><a href="#">哈利波特大</a></li> <li><a href="#">負周幾</a></li> <li><a href="#">尼美</a></li> </ul> </div> <script> adaptUILayout.adapt(480); //適配當前頁面 </script> </body> </html>
------------------------------------------------------------------------------------------------------
本篇文章為博主原創,如需轉載本篇文章,請保留原始地址:、
------------------------------------------------------------------------------------------------------
本文釋出以來,有很多童鞋瀏覽,提問交流,卻腫麼只有2個推薦捏,反對竟然也一個都沒有?交流啊,要交流啊騷年們。
如果本文有幸吸引您閱讀到這裡的話,那俺就厚著臉皮問您要一個推薦,如果您覺得本文無什可取之處,那您就反對一下,若果能得到您對本文的留言,那就是俺莫大的榮幸。
最後,感謝您閱讀本文,工作愉快。。。