diff options
| author | Grace Kloba <klobag@google.com> | 2010-03-10 13:25:34 -0800 |
|---|---|---|
| committer | Grace Kloba <klobag@google.com> | 2010-03-11 11:40:46 -0800 |
| commit | c6f95fe5236d8bd60ac01e7feb422f6fac70bf6f (patch) | |
| tree | 8b89043b0bc500e964c831447b140b30e16334d6 /core/java/android/webkit/WebView.java | |
| parent | feec868c990bfec050a05b68adfd385380e77c65 (diff) | |
Implement smart-zoom per Adobe request.
When double tap on plugin object, we toggle between
centering plugin object and overview mode.
Fix http://b/issue?id=2501726
Diffstat (limited to 'core/java/android/webkit/WebView.java')
| -rw-r--r-- | core/java/android/webkit/WebView.java | 132 |
1 files changed, 114 insertions, 18 deletions
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 5099cd45d1c3..825ea464186d 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -479,8 +479,6 @@ public class WebView extends AbsoluteLayout private boolean mSupportMultiTouch; // use the framework's ScaleGestureDetector to handle multi-touch private ScaleGestureDetector mScaleDetector; - // minimum scale change during multi-touch zoom - private static float PREVIEW_SCALE_INCREMENT = 0.01f; // the anchor point in the document space where VIEW_SIZE_CHANGED should // apply to @@ -619,6 +617,8 @@ public class WebView extends AbsoluteLayout static int DEFAULT_SCALE_PERCENT; private float mDefaultScale; + private static float MINIMUM_SCALE_INCREMENT = 0.01f; + // set to true temporarily during ScaleGesture triggered zoom private boolean mPreviewZoomOnly = false; @@ -2306,7 +2306,8 @@ public class WebView extends AbsoluteLayout boolean clampedY) { mInOverScrollMode = false; int maxX = computeMaxScrollX(); - if (maxX == 0 && (Math.abs(mMinZoomScale - mMaxZoomScale) < 0.01f) + if (maxX == 0 && (Math.abs(mMinZoomScale - mMaxZoomScale) + < MINIMUM_SCALE_INCREMENT) || !getSettings().supportZoom() || !getSettings().getUseWideViewPort()) { // do not over scroll x if the page just fits the screen and it @@ -4466,7 +4467,8 @@ public class WebView extends AbsoluteLayout mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY); // don't reflow when zoom in; when zoom out, do reflow if the // new scale is almost minimum scale; - boolean reflowNow = (mActualScale - mMinZoomScale <= 0.01f) + boolean reflowNow = (mActualScale - mMinZoomScale + <= MINIMUM_SCALE_INCREMENT) || ((mActualScale <= 0.8 * mTextWrapScale)); // force zoom after mPreviewZoomOnly is set to false so that the // new view size will be passed to the WebKit @@ -4493,7 +4495,7 @@ public class WebView extends AbsoluteLayout public boolean onScale(ScaleGestureDetector detector) { float scale = (float) (Math.round(detector.getScaleFactor() * mActualScale * 100) / 100.0); - if (Math.abs(scale - mActualScale) >= PREVIEW_SCALE_INCREMENT) { + if (Math.abs(scale - mActualScale) >= MINIMUM_SCALE_INCREMENT) { mPreviewZoomOnly = true; // limit the scale change per step if (scale > mActualScale) { @@ -5430,17 +5432,17 @@ public class WebView extends AbsoluteLayout invalidate(); } - private boolean zoomWithPreview(float scale) { + private boolean zoomWithPreview(float scale, boolean updateTextWrapScale) { float oldScale = mActualScale; mInitialScrollX = mScrollX; mInitialScrollY = mScrollY; // snap to DEFAULT_SCALE if it is close - if (scale > (mDefaultScale - 0.05) && scale < (mDefaultScale + 0.05)) { + if (Math.abs(scale - mDefaultScale) < MINIMUM_SCALE_INCREMENT) { scale = mDefaultScale; } - setNewZoomScale(scale, true, false); + setNewZoomScale(scale, updateTextWrapScale, false); if (oldScale != mActualScale) { // use mZoomPickerScale to see zoom preview first @@ -5552,7 +5554,7 @@ public class WebView extends AbsoluteLayout mZoomCenterY = getViewHeight() * .5f; mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX); mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY); - return zoomWithPreview(mActualScale * 1.25f); + return zoomWithPreview(mActualScale * 1.25f, true); } /** @@ -5567,7 +5569,7 @@ public class WebView extends AbsoluteLayout mZoomCenterY = getViewHeight() * .5f; mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX); mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY); - return zoomWithPreview(mActualScale * 0.8f); + return zoomWithPreview(mActualScale * 0.8f, true); } private void updateSelection() { @@ -5692,6 +5694,84 @@ public class WebView extends AbsoluteLayout } } + /* + * Return true if the view (Plugin) is fully visible and maximized inside + * the WebView. + */ + private boolean isPluginFitOnScreen(ViewManager.ChildView view) { + int viewWidth = getViewWidth(); + int viewHeight = getViewHeightWithTitle(); + float scale = Math.min((float) viewWidth / view.width, + (float) viewHeight / view.height); + if (scale < mMinZoomScale) { + scale = mMinZoomScale; + } else if (scale > mMaxZoomScale) { + scale = mMaxZoomScale; + } + if (Math.abs(scale - mActualScale) < MINIMUM_SCALE_INCREMENT) { + if (contentToViewX(view.x) >= mScrollX + && contentToViewX(view.x + view.width) <= mScrollX + + viewWidth + && contentToViewY(view.y) >= mScrollY + && contentToViewY(view.y + view.height) <= mScrollY + + viewHeight) { + return true; + } + } + return false; + } + + /* + * Maximize and center the view inside the WebView. If the zoom doesn't need + * to be changed, do an animated scroll to center it. If the zoom needs to + * be changed, find the zoom center and do a smooth zoom transition. + */ + private void centerPluginOnScreen(ViewManager.ChildView child) { + int viewWidth = getViewWidth(); + int viewHeight = getViewHeightWithTitle(); + float scale = Math.min((float) viewWidth / child.width, + (float) viewHeight / child.height); + if (scale < mMinZoomScale) { + scale = mMinZoomScale; + } else if (scale > mMaxZoomScale) { + scale = mMaxZoomScale; + } + if (Math.abs(scale - mActualScale) < MINIMUM_SCALE_INCREMENT) { + pinScrollTo( + contentToViewX(child.x + child.width / 2) - viewWidth / 2, + contentToViewY(child.y + child.height / 2) - viewHeight / 2, + true, 0); + } else { + int oldScreenX = contentToViewX(child.x) - mScrollX; + int newPluginX = (int) (child.x * scale); + int newPluginWidth = (int) (child.width * scale); + int newMaxWidth = (int) (mContentWidth * scale); + int newScreenX = (viewWidth - newPluginWidth) / 2; + // pin the newX to the WebView + if (newScreenX > newPluginX) { + newScreenX = newPluginX; + } else if (newScreenX > (newMaxWidth - newPluginX - newPluginWidth)) { + newScreenX = viewWidth - (newMaxWidth - newPluginX); + } + mZoomCenterX = (oldScreenX * scale - newScreenX * mActualScale) + / (scale - mActualScale); + int oldScreenY = contentToViewY(child.y) - mScrollY; + int newPluginY = (int) (child.y * scale) + getTitleHeight(); + int newPluginHeight = (int) (child.height * scale); + int newMaxHeight = (int) (mContentHeight * scale) + getTitleHeight(); + int newScreenY = (viewHeight - newPluginHeight) / 2; + // pin the newY to the WebView + if (newScreenY > newPluginY) { + newScreenY = newPluginY; + } else if (newScreenY > (newMaxHeight - newPluginY - newPluginHeight)) { + newScreenY = viewHeight - (newMaxHeight - newPluginY); + } + mZoomCenterY = (oldScreenY * scale - newScreenY * mActualScale) + / (scale - mActualScale); + zoomWithPreview(scale, false); + } + } + // Rule for double tap: // 1. if the current scale is not same as the text wrap scale and layout // algorithm is NARROW_COLUMNS, fit to column; @@ -5720,22 +5800,36 @@ public class WebView extends AbsoluteLayout } } settings.setDoubleTapToastCount(0); + ViewManager.ChildView plugin = mViewManager.hitTest(mAnchorX, mAnchorY); + if (plugin != null) { + if (isPluginFitOnScreen(plugin)) { + mInZoomOverview = true; + // Force the titlebar fully reveal in overview mode + if (mScrollY < getTitleHeight()) mScrollY = 0; + zoomWithPreview((float) getViewWidth() / mZoomOverviewWidth, + true); + } else { + mInZoomOverview = false; + centerPluginOnScreen(plugin); + } + return; + } boolean zoomToDefault = false; if ((settings.getLayoutAlgorithm() == WebSettings.LayoutAlgorithm.NARROW_COLUMNS) - && (Math.abs(mActualScale - mTextWrapScale) >= 0.01f)) { + && (Math.abs(mActualScale - mTextWrapScale) >= MINIMUM_SCALE_INCREMENT)) { setNewZoomScale(mActualScale, true, true); float overviewScale = (float) getViewWidth() / mZoomOverviewWidth; - if (Math.abs(mActualScale - overviewScale) < 0.01f) { + if (Math.abs(mActualScale - overviewScale) < MINIMUM_SCALE_INCREMENT) { mInZoomOverview = true; } } else if (!mInZoomOverview) { float newScale = (float) getViewWidth() / mZoomOverviewWidth; - if (Math.abs(mActualScale - newScale) >= 0.01f) { + if (Math.abs(mActualScale - newScale) >= MINIMUM_SCALE_INCREMENT) { mInZoomOverview = true; // Force the titlebar fully reveal in overview mode if (mScrollY < getTitleHeight()) mScrollY = 0; - zoomWithPreview(newScale); - } else if (Math.abs(mActualScale - mDefaultScale) >= 0.01f) { + zoomWithPreview(newScale, true); + } else if (Math.abs(mActualScale - mDefaultScale) >= MINIMUM_SCALE_INCREMENT) { zoomToDefault = true; } } else { @@ -5758,7 +5852,7 @@ public class WebView extends AbsoluteLayout mZoomCenterX = 0; } } - zoomWithPreview(mDefaultScale); + zoomWithPreview(mDefaultScale, true); } } @@ -6103,7 +6197,8 @@ public class WebView extends AbsoluteLayout scale = restoreState.mTextWrapScale; } setNewZoomScale(scale, Math.abs(scale - - mTextWrapScale) >= 0.01f, false); + - mTextWrapScale) >= MINIMUM_SCALE_INCREMENT, + false); } setContentScrollTo(restoreState.mScrollX, restoreState.mScrollY); @@ -6156,7 +6251,8 @@ public class WebView extends AbsoluteLayout - mZoomOverviewWidth) > 1) { setNewZoomScale((float) viewWidth / mZoomOverviewWidth, Math.abs(mActualScale - - mTextWrapScale) < 0.01f, false); + - mTextWrapScale) < MINIMUM_SCALE_INCREMENT, + false); } } if (draw.mFocusSizeChanged && inEditingMode()) { |
