禁止APP内Webview页面跟随系统缩放字号

最近开始做适配移动端的网页,通过APP内部的Webview展示。为了在不同分辨率的设备上都能按相同的布局来展示,使用了rem布局的页面自适应方式:

(function (doc, win) {
  var docEl = doc.documentElement,
  resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
  recalc = function () {
    var clientWidth = docEl.clientWidth;
    if (!clientWidth) return;
    docEl.style.fontSize = 100 * (clientWidth / 320) + 'px';
    alert(docEl.style.fontSize);
  };

  // Abort if browser does not support addEventListener
  if (!doc.addEventListener) return;
  win.addEventListener(resizeEvt, recalc, false);
  doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);

样式表中文字的字号,元素的高宽、间距等都以rem为单位。

但是测试的时候发现了一个很糟糕的问题,当Android手机将系统的字号大小设置为非标准时,页面的布局受到了严重的影响,包括字号在内,所有以rem为单位的属性都被放大或者缩小了。为了保证布局不受影响,在网上查阅了一些应对这个问题的解决方案,经过了自己的实践验证后整理如下:

iOS

在iPhone系统设置中的“更大字体”里调整字号后,各个应用里中Webview里的文字大小似乎没有受到影响。但是对于诸如微信、UC浏览器等可以在APP里设置网页字体大小的应用,还是有限制调整字号的需求的。它们调整字体大小是通过给body设置-webkit-text-size-adjust属性实现的,因此只要限制这个属性不被修改即可:

body {
    -webkit-text-size-adjust: none !important;
}

Android

如果是在自己开发的APP中,可以在客户端的WebView组件中设置字体默认的缩放比例,以避免手机系统的字体修改对页面字体及布局造成影响。

WebSettings settings = webView.getSettings();
settings.setTextZoom(100);

如果APP自身就不希望被系统字号影响到展示效果,也可以在activity基类中增加设置config的代码,同样可以使得APP内置网页字号不受系统字号影响。

如果是在微信环境中,参考微信开放平台的文档,须通过WeixinJSBridge对象将网页的字体大小设置为默认大小,并且重写设置字体大小的方法,让用户不能在该网页下设置字体大小。

(function() {
  if (typeof WeixinJSBridge == "object" && typeof WeixinJSBridge.invoke == "function") {
    handleFontSize();
  } else {
    if (document.addEventListener) {
      document.addEventListener("WeixinJSBridgeReady", handleFontSize, false);
    } else if (document.attachEvent) {
      document.attachEvent("WeixinJSBridgeReady", handleFontSize);
      document.attachEvent("onWeixinJSBridgeReady", handleFontSize);
    }
  }
  function handleFontSize() {
    // 设置网页字体为默认大小
    WeixinJSBridge.invoke('setFontSizeCallback', { 'fontSize' : 0 });
    // 重写设置网页字体大小的事件
    WeixinJSBridge.on('menu:setfont', function() {
      WeixinJSBridge.invoke('setFontSizeCallback', { 'fontSize' : 0 });
    });
  }
})();

实际上上述代码在iOS环境下同样有效。

需要注意的是,这段代码在Android微信环境中会延时生效。如果预先设置字号大小不是“标准”,打开网页时页面会按照设置的缩放效果展示约1秒(等WeixinJSBridge对象初始化完成)后才调整到正常。这个时间差的问题目前暂时没有合适的解决方式,只能通过增加loading动画、延迟展示时间等方式来尽量消除用户的不适感。

Leave a Reply