日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

webview布局适配实践

發布時間:2023/12/2 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 webview布局适配实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、相關概念

1、viewport:移動設備(包括webview)用來顯示網頁的那一塊區域;
2、devicePixelRatio屬性(別名像素比,簡稱dpr):window.devicePixelRatio =物理像素 / 獨立像素(css中的px);
3、rem:相對于根元素(即html元素)font-size計算值的倍數(我以前真不大清楚)。

上面許多概念請看這篇 http://www.cnblogs.com/2050/p/3877280.html

二、淘寶flexible.js

下面是flexible.js的源碼:

;(function(win, lib) {var doc = win.document;var docEl = doc.documentElement;var metaEl = doc.querySelector('meta[name="viewport"]');var flexibleEl = doc.querySelector('meta[name="flexible"]');var dpr = 0;var scale = 0;var tid;var flexible = lib.flexible || (lib.flexible = {});if (metaEl) {console.warn('將根據已有的meta標簽來設置縮放比例');var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.] )/);if (match) {scale = parseFloat(match[1]);dpr = parseInt(1 / scale);}} else if (flexibleEl) {var content = flexibleEl.getAttribute('content');if (content) {var initialDpr = content.match(/initial\-dpr=([\d\.] )/);var maximumDpr = content.match(/maximum\-dpr=([\d\.] )/);if (initialDpr) {dpr = parseFloat(initialDpr[1]);scale = parseFloat((1 / dpr).toFixed(2)); }if (maximumDpr) {dpr = parseFloat(maximumDpr[1]);scale = parseFloat((1 / dpr).toFixed(2)); }}}if (!dpr && !scale) {var isAndroid = win.navigator.appVersion.match(/android/gi);var isIPhone = win.navigator.appVersion.match(/iphone/gi);var devicePixelRatio = win.devicePixelRatio;if (isIPhone) {// iOS下,對于2和3的屏,用2倍的方案,其余的用1倍方案if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) { dpr = 3;} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){dpr = 2;} else {dpr = 1;}} else {// 其他設備下,仍舊使用1倍的方案dpr = 1;}scale = 1 / dpr;}docEl.setAttribute('data-dpr', dpr);if (!metaEl) {metaEl = doc.createElement('meta');metaEl.setAttribute('name', 'viewport');metaEl.setAttribute('content', 'initial-scale=' scale ', maximum-scale=' scale ', minimum-scale=' scale ', user-scalable=no');if (docEl.firstElementChild) {docEl.firstElementChild.appendChild(metaEl);} else {var wrap = doc.createElement('div');wrap.appendChild(metaEl);doc.write(wrap.innerHTML);}}function refreshRem(){var width = docEl.getBoundingClientRect().width;if (width / dpr > 540) {width = 540 * dpr;}var rem = width / 10;docEl.style.fontSize = rem 'px';flexible.rem = win.rem = rem;}win.addEventListener('resize', function() {clearTimeout(tid);tid = setTimeout(refreshRem, 300);}, false);win.addEventListener('pageshow', function(e) {if (e.persisted) {clearTimeout(tid);tid = setTimeout(refreshRem, 300);}}, false);if (doc.readyState === 'complete') {doc.body.style.fontSize = 12 * dpr 'px';} else {doc.addEventListener('DOMContentLoaded', function(e) {doc.body.style.fontSize = 12 * dpr 'px';}, false);}refreshRem();flexible.dpr = win.dpr = dpr;flexible.refreshRem = refreshRem;flexible.rem2px = function(d) {var val = parseFloat(d) * this.rem;if (typeof d === 'string' && d.match(/rem$/)) {val = 'px';}return val;}flexible.px2rem = function(d) {var val = parseFloat(d) / this.rem;if (typeof d === 'string' && d.match(/px$/)) {val = 'rem';}return val;} })(window, window['lib'] || (window['lib'] = {}));

我以前做移動端適配都采用百分百布局,通常粘貼復制下面一段代碼,而且還樂此不疲

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">

實際網上大部分移動端適配的方案都是rem布局外加使用flexble.js原理,其核心要點(以iPhone6為例)如下:
1、手動設置上述meta viewport( initial-scale=1.0)標簽,加載flexble.js成功后會在html標簽設置data-dpr=1,font-size=37.5px;
??1rem = 37.5px = doc.documentElement.getBoundingClientRect().width/10 “px”;
2、如果沒有手動添加meta viewport標簽,flexble.js會動態設置此標簽,但是和上面的情況有區別,會執行如下流程:
??a、獲取devicePixelRatio(dpr)值,iPhone6值為2;
??b、設置scale = 1/dpr = 0.5;
??c、渲染viewport標簽,動態設置html標簽屬性data-dpr=2,font-size=75px;;
??d、rem與1的獲取方式相同,只不過這里面的1rem=75px;

所以flexible.js通過這兩種方式布局,如果在css文件中設置一個div標簽的寬度,設計圖的長度是75px,第一種方式需設置width=2rem,第二種需設置width=1rem。

??以上呈現的方式適合蘋果手機,安卓手機flexble.js默認dpr值為1,所以網上大部分的結論是flexible.js不適合安卓手機,既然安卓手機devicePixelRatio 也有約等于1,2,3,為什么就不能用呢。而且flexble.js只考慮豎屏的情況,設置doc寬度不大于540px。

三、我遇到的情況

??工作中一直在安卓webview中進行web開發,從接手項目的css樣式中都是100%布局,后來機器越來越多,分辨率600到1920不等,而且rom層默認設置也會對機型的分辨率有影響。關鍵布局是否合理,一般由產品和UI決定,原項目通過media標簽對各種機型不同樣式適配,冗余度和復雜度高,可維護性差。
?? UI設計師通常以一種機型為基準進行設計,比如說UI設計師給的設計圖是1920 x 1200,那么她會以這個機型衡量其它機型,如960 x 600的機型就應該等比例縮放。布局從視覺上看不會有差異,這才達到她理想的兼容適配。

四、修改flexible.js

??根據上面遇到的情況,如果以rem布局,在1920 x 1200分辨率下是1rem=192px,那么在960 x 600分辨率的機型中1rem = 96px,這里將document寬度十等分。既然這樣我也可以運用flexble.js,只需修改相關邏輯就行,而且改動不大,修改后如下:

'use strict' const doc = window.document; const docEl = doc.documentElement; let metaEl = doc.querySelector('meta[name="viewport"]'); let dpr=0,scale=0,tid=null; let msoFlex = {};if (!dpr && !scale) {const devicePixelRatio = window.devicePixelRatio;if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) { dpr = 3;} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){dpr = 2;} else {dpr = 1;}scale = 1 / dpr; } docEl.setAttribute('data-dpr', dpr); if (!metaEl) {metaEl = doc.createElement('meta');metaEl.setAttribute('name', 'viewport');metaEl.setAttribute('content', 'initial-scale=' scale ', maximum-scale=' scale ', minimum-scale=' scale ', user-scalable=no');if (docEl.firstElementChild) {docEl.firstElementChild.appendChild(metaEl);} else {const wrap = doc.createElement('div');wrap.appendChild(metaEl);doc.write(wrap.innerHTML);} } const refreshRem = function(){const width = docEl.getBoundingClientRect().width;const rem = width / 10;docEl.style.fontSize = rem 'px';msoFlex.rem = rem; }window.addEventListener('resize', function() {clearTimeout(tid);tid = setTimeout(refreshRem, 300); }, false); window.addEventListener('pageshow', function(e) {if (e.persisted) {clearTimeout(tid);tid = setTimeout(refreshRem, 300);} }, false); if (doc.readyState === 'complete') {doc.body.style.fontSize = 12 * dpr 'px'; } else {doc.addEventListener('DOMContentLoaded', function(e) {doc.body.style.fontSize = 12 * dpr 'px';}, false); }refreshRem(); msoFlex.dpr = dpr; msoFlex.refreshRem = refreshRem; msoFlex.rem2px = function(d) {var val = parseFloat(d) * this.rem;if (typeof d === 'string' && d.match(/rem$/)) {val = 'px';}return val; } msoFlex.px2rem = function(d) {var val = parseFloat(d) / this.rem;if (typeof d === 'string' && d.match(/px$/)) {val = 'rem';}return val; }

修改點如下:
??1、將flexible.js手動設置viewport標簽的邏輯刪除,如果不刪除,dpr不是1的情況,在viewport標簽縮放scale值是默認的1.0,1px可能就不是真正1像素寬度,那么隨之而來就是你要適配1像素寬度,網上有很多方案,比如偽元素,圖片代替,另一種就是縮放,所以用代碼動態設置viewport標簽,scale值會隨dpr值變化,1px也會縮放的,這里面我一般在樣式中設置1像素寬度的單位就是px,而非rem;
??2、將flexible.js對iPhone的retain屏1,2,3設置三種情況同樣適用安卓機,并且document寬度由540改為不限制寬度。
??3、命名改變了,flexible改成msoFlex,為了區別flexible.js。

五、項目微調

??1在vue工程中引用mso-flex,先npm install mso-flex --save-dev,然后在main.js頭部引用import "mso-flex/mso-flex.js"即可(可以用yarn)。
??2、字體的問題,一般如果UI和產品不介意字體有瑕疵的話可以不用修改,因為用rem換算的過程中,字體可能會出現奇數和小數的字體(13px或者13.343px),這樣的字體像素眼看起來有模糊。如果你用的是scss樣式處理器@mixin方法對data-dpr判斷,根據屬性值的不同,設置字體大小。
??3、rem和px轉換,需安裝postcss-pxtorem,在書寫樣式的時候直接在psd文件中量大小像素作為長寬的數值,不需要每次用計算器將px換算成rem,方便快捷。

六、vue-cli3.0使用配置

??為了觀察效果,直接準備運行vue-cli工程,發現vue-cli大變樣,真的體會到在前端日益發展的過程中學不動了。
??通過官網 yarn 命令啟動vue服務,先后安裝
??yarn add -D mso-flex;
??yarn add -D sass-loader node-sass;
??yarn add -D postcss-pxtorem;
??下面是工程目錄(真的簡潔很多)


上面vue.config.js是新建配置相關loader, 但是3.0不需要配sass-loader,直接可以引用,mso-flex.js在main.js 頭部直接可以引用

postcss-pxtorem在package.json配置,其中“rootValue":192的值是根據設計稿的長度除10設置的。 pxtorem中,對于想忽略的px寫成大寫即可,諸如 width:50PX;

以上就是在webview 安卓機布局實踐,沒有太多原理,也非長篇大論,如果各位大神看到開心,麻煩點個贊,謝謝哈~_~,實踐的代碼地址:https://github.com/yuelinghunyu/mso-flex.git

總結

以上是生活随笔為你收集整理的webview布局适配实践的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。