主页 > 原创 > Android 4.1 4.2 webkit开启默认缩放设置后meta中target-densitydpi配置会影响其他页面的解决方法

Android 4.1 4.2 webkit开启默认缩放设置后meta中target-densitydpi配置会影响其他页面的解决方法

前文中打开了默认的缩放设置后,当遇到网页内容那个中包含target-densitydpi键值时会导致后续访问的页面的dpi被更改。这是由于webkit在framework层中meta和设置dpi都是调用的updateDefaultDesity()方法导致。

进行追踪发现是mDefaultScale变量的值更改起到了关键作用。即使追踪到webkit底层实现部分,亦不能很好解决该问题,最终通过增加延时更改mDefaultScale值来解决该问题。

1.更改frameworks\base\core\java\android\webkit目录下的WebViewClassic.java文件,修改如下内容:

case UPDATE_ZOOM_DENSITY: {
 final float density = (Float) msg.obj;
  // Modified by xdtianyu [start]
 //mZoomManager.updateDefaultZoomDensity(density);
 mZoomManager.updateMetaZoomDensity(density);
  // Modified by xdtianyu [end]
 break;
}

2.如上所示,在ZoomManager中增加updateMetaZoomDensity()方法:

public void updateDefaultZoomDensity(float density) {
 assert density > 0;

 if (Math.abs(density - mDefaultScale) > MINIMUM_SCALE_INCREMENT) {
    // Remember the current zoom density before it gets changed.
    final float originalDefault = mDefaultScale;
    // set the new default density
    mDisplayDensity = density;
    setDefaultZoomScale(density);
   float scaleChange = (originalDefault > 0.0) ? density / originalDefault: 1.0f;
    // adjust the scale if it falls outside the new zoom bounds
   setZoomScale(mActualScale * scaleChange, true);
 }
}

// Add by xdtianyu [start]
public void updateMetaZoomDensity(float density) {
  assert density > 0;

 if (Math.abs(density - mDefaultScale) > MINIMUM_SCALE_INCREMENT) {
    // Remember the current zoom density before it gets changed.
    final float originalDefault = mDefaultScale;
    // set the new default density
    mDisplayDensity = density;
    setMetaZoomScale(density);
    float scaleChange = (originalDefault > 0.0) ? density / originalDefault: 1.0f;
    // adjust the scale if it falls outside the new zoom bounds
   setZoomScale(mActualScale * scaleChange, true);
 }
}

private void setMetaZoomScale(float defaultScale) {
 final float originalDefault = mDefaultScale;
  setDefaultZoomScale(defaultScale);
  TimerTask task = new TimerTask() {
    public void run() {
     mDefaultScale = originalDefault;
    }
 }
 Timer timer = new Timer();
  timer.schedule(task, 500);
}
// Add by xdtianyu [end]

private void setDefaultZoomScale(float defaultScale) {
 final float originalDefault = mDefaultScale;
  mDefaultScale = defaultScale;
 mInvDefaultScale = 1 / defaultScale;
  mDefaultMaxZoomScale = defaultScale * DEFAULT_MAX_ZOOM_SCALE_FACTOR;
  mDefaultMinZoomScale = defaultScale * DEFAULT_MIN_ZOOM_SCALE_FACTOR;
  if (originalDefault > 0.0 && mMaxZoomScale > 0.0) {
   // Keeps max zoom scale when zoom density changes.
    mMaxZoomScale = defaultScale / originalDefault * mMaxZoomScale;
 } else {
    mMaxZoomScale = mDefaultMaxZoomScale;
 }
 if (originalDefault > 0.0 && mMinZoomScale > 0.0) {
   // Keeps min zoom scale when zoom density changes.
    mMinZoomScale = defaultScale / originalDefault * mMinZoomScale;
 } else {
    mMinZoomScale = mDefaultMinZoomScale;
 }
 if (!exceedsMinScaleIncrement(mMinZoomScale, mMaxZoomScale)) {
    mMaxZoomScale = mMinZoomScale;
  }
 sanitizeMinMaxScales();
}

注意import timer包,至此修改完成。

关于meta在底层的处理则可以参考external\webkit\Source\WebCore\dom目录下的Document.cpp其中部分代码如下所示:

void Document::processArguments(const String& features, void* data, ArgumentsCallback callback)
{
    // Tread lightly in this code -- it was specifically designed to mimic Win IE's parsing behavior.
    int keyBegin, keyEnd;
    int valueBegin, valueEnd;

    int i = 0;
    int length = features.length();
    String buffer = features.lower();
    while (i < length) {
        // skip to first non-separator, but don't skip past the end of the string
        while (isSeparator(buffer[i])) {
            if (i >= length)
                break;
            i++;
        }
        keyBegin = i;

        // skip to first separator
        while (!isSeparator(buffer[i]))
            i++;
        keyEnd = i;

        // skip to first '=', but don't skip past a ',' or the end of the string
        while (buffer[i] != '=') {
            if (buffer[i] == ',' || i >= length)
                break;
            i++;
        }

        // skip to first non-separator, but don't skip past a ',' or the end of the string
        while (isSeparator(buffer[i])) {
            if (buffer[i] == ',' || i >= length)
                break;
            i++;
        }
        valueBegin = i;

        // skip to first separator
        while (!isSeparator(buffer[i]))
            i++;
        valueEnd = i;

        ASSERT(i <= length);

        String keyString = buffer.substring(keyBegin, keyEnd - keyBegin);
        String valueString = buffer.substring(valueBegin, valueEnd - valueBegin);
#ifdef ANDROID_META_SUPPORT
        if (frame())
            frame()->settings()->setMetadataSettings(keyString, valueString);
        if (callback && data)
#endif
            callback(keyString, valueString, this, data);
    }
}

void Document::processViewport(const String& features)
{
    ASSERT(!features.isNull());

    m_viewportArguments = ViewportArguments();
    processArguments(features, (void*)&m_viewportArguments, &setViewportFeature);

    Frame* frame = this->frame();
    if (!frame || !frame->page())
        return;

    frame->page()->updateViewportArguments();
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注