Move pinch-to-zoom logic into ZoomManager.
This CL is one in a series of CL's that moves the zoom logic from WebView into ZoomManager. Change-Id: I9980dd78dbc3345d465d4f39afcfd2f025f45bcb http://b/2671604
This commit is contained in:
@@ -520,11 +520,6 @@ public class WebView extends AbsoluteLayout
|
||||
private static final int MOTIONLESS_IGNORE = 3;
|
||||
private int mHeldMotionless;
|
||||
|
||||
// whether support multi-touch
|
||||
private boolean mSupportMultiTouch;
|
||||
// use the framework's ScaleGestureDetector to handle multi-touch
|
||||
private ScaleGestureDetector mScaleDetector;
|
||||
|
||||
// An instance for injecting accessibility in WebViews with disabled
|
||||
// JavaScript or ones for which no accessibility script exists
|
||||
private AccessibilityInjector mAccessibilityInjector;
|
||||
@@ -873,16 +868,7 @@ public class WebView extends AbsoluteLayout
|
||||
}
|
||||
|
||||
void updateMultiTouchSupport(Context context) {
|
||||
WebSettings settings = getSettings();
|
||||
mSupportMultiTouch = context.getPackageManager().hasSystemFeature(
|
||||
PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)
|
||||
&& settings.supportZoom() && settings.getBuiltInZoomControls();
|
||||
if (mSupportMultiTouch && (mScaleDetector == null)) {
|
||||
mScaleDetector = new ScaleGestureDetector(context,
|
||||
new ScaleDetectorListener());
|
||||
} else if (!mSupportMultiTouch && (mScaleDetector != null)) {
|
||||
mScaleDetector = null;
|
||||
}
|
||||
mZoomManager.updateMultiTouchSupport(context);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
@@ -2125,7 +2111,7 @@ public class WebView extends AbsoluteLayout
|
||||
private Rect mLastGlobalRect;
|
||||
|
||||
Rect sendOurVisibleRect() {
|
||||
if (mZoomManager.mPreviewZoomOnly) return mLastVisibleRectSent;
|
||||
if (mZoomManager.isPreventingWebkitUpdates()) return mLastVisibleRectSent;
|
||||
|
||||
Rect rect = new Rect();
|
||||
calcOurContentVisibleRect(rect);
|
||||
@@ -2217,7 +2203,7 @@ public class WebView extends AbsoluteLayout
|
||||
* @return true if new values were sent
|
||||
*/
|
||||
boolean sendViewSizeZoom(boolean force) {
|
||||
if (mZoomManager.mPreviewZoomOnly) return false;
|
||||
if (mZoomManager.isPreventingWebkitUpdates()) return false;
|
||||
|
||||
int viewWidth = getViewWidth();
|
||||
int newWidth = Math.round(viewWidth * mZoomManager.mInvActualScale);
|
||||
@@ -2240,7 +2226,8 @@ public class WebView extends AbsoluteLayout
|
||||
data.mHeight = newHeight;
|
||||
data.mTextWrapWidth = Math.round(viewWidth / mZoomManager.mTextWrapScale);
|
||||
data.mScale = mZoomManager.mActualScale;
|
||||
data.mIgnoreHeight = mZoomManager.isZoomAnimating() && !mHeightCanMeasure;
|
||||
data.mIgnoreHeight = mZoomManager.isFixedLengthAnimationInProgress()
|
||||
&& !mHeightCanMeasure;
|
||||
data.mAnchorX = mAnchorX;
|
||||
data.mAnchorY = mAnchorY;
|
||||
mWebViewCore.sendMessage(EventHub.VIEW_SIZE_CHANGED, data);
|
||||
@@ -3219,15 +3206,6 @@ public class WebView extends AbsoluteLayout
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Need to adjust the WebTextView after a change in zoom, since mActualScale
|
||||
* has changed. This is especially important for password fields, which are
|
||||
* drawn by the WebTextView, since it conveys more information than what
|
||||
* webkit draws. Thus we need to reposition it to show in the correct
|
||||
* place.
|
||||
*/
|
||||
private boolean mNeedToAdjustWebTextView;
|
||||
|
||||
private boolean didUpdateTextViewBounds(boolean allowIntersect) {
|
||||
Rect contentBounds = nativeFocusCandidateNodeBounds();
|
||||
Rect vBox = contentToViewRect(contentBounds);
|
||||
@@ -3265,6 +3243,32 @@ public class WebView extends AbsoluteLayout
|
||||
canvas.setDrawFilter(null);
|
||||
}
|
||||
|
||||
private void onZoomAnimationStart() {
|
||||
// If it is in password mode, turn it off so it does not draw misplaced.
|
||||
if (inEditingMode() && nativeFocusCandidateIsPassword()) {
|
||||
mWebTextView.setInPassword(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void onZoomAnimationEnd() {
|
||||
// adjust the edit text view if needed
|
||||
if (inEditingMode() && didUpdateTextViewBounds(false) && nativeFocusCandidateIsPassword()) {
|
||||
// If it is a password field, start drawing the WebTextView once
|
||||
// again.
|
||||
mWebTextView.setInPassword(true);
|
||||
}
|
||||
}
|
||||
|
||||
void onFixedLengthZoomAnimationStart() {
|
||||
WebViewCore.pauseUpdatePicture(getWebViewCore());
|
||||
onZoomAnimationStart();
|
||||
}
|
||||
|
||||
void onFixedLengthZoomAnimationEnd() {
|
||||
WebViewCore.resumeUpdatePicture(mWebViewCore);
|
||||
onZoomAnimationEnd();
|
||||
}
|
||||
|
||||
private void drawCoreAndCursorRing(Canvas canvas, int color,
|
||||
boolean drawCursorRing) {
|
||||
if (mDrawHistory) {
|
||||
@@ -3273,7 +3277,7 @@ public class WebView extends AbsoluteLayout
|
||||
return;
|
||||
}
|
||||
|
||||
boolean animateZoom = mZoomManager.isZoomAnimating();
|
||||
boolean animateZoom = mZoomManager.isFixedLengthAnimationInProgress();
|
||||
boolean animateScroll = ((!mScroller.isFinished()
|
||||
|| mVelocityTracker != null)
|
||||
&& (mTouchMode != TOUCH_DRAG_MODE ||
|
||||
@@ -3292,39 +3296,7 @@ public class WebView extends AbsoluteLayout
|
||||
}
|
||||
}
|
||||
if (animateZoom) {
|
||||
final float[] zoomValues = mZoomManager.animateZoom();
|
||||
final boolean isStillAnimating = mZoomManager.isZoomAnimating();
|
||||
|
||||
if (isStillAnimating) {
|
||||
invalidate();
|
||||
} else {
|
||||
WebViewCore.resumeUpdatePicture(mWebViewCore);
|
||||
// call invalidate() again to draw with the final filters
|
||||
invalidate();
|
||||
if (mNeedToAdjustWebTextView) {
|
||||
mNeedToAdjustWebTextView = false;
|
||||
if (didUpdateTextViewBounds(false)
|
||||
&& nativeFocusCandidateIsPassword()) {
|
||||
// If it is a password field, start drawing the
|
||||
// WebTextView once again.
|
||||
mWebTextView.setInPassword(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
canvas.translate(zoomValues[0], zoomValues[1]);
|
||||
canvas.scale(zoomValues[2], zoomValues[2]);
|
||||
|
||||
if (inEditingMode() && !mNeedToAdjustWebTextView && isStillAnimating) {
|
||||
// The WebTextView is up. Keep track of this so we can adjust
|
||||
// its size and placement when we finish zooming
|
||||
mNeedToAdjustWebTextView = true;
|
||||
// If it is in password mode, turn it off so it does not draw
|
||||
// misplaced.
|
||||
if (nativeFocusCandidateIsPassword()) {
|
||||
mWebTextView.setInPassword(false);
|
||||
}
|
||||
}
|
||||
mZoomManager.animateZoom(canvas);
|
||||
} else {
|
||||
canvas.scale(mZoomManager.mActualScale, mZoomManager.mActualScale);
|
||||
}
|
||||
@@ -3339,7 +3311,7 @@ public class WebView extends AbsoluteLayout
|
||||
invalidate();
|
||||
}
|
||||
mWebViewCore.drawContentPicture(canvas, color,
|
||||
(animateZoom || mZoomManager.mPreviewZoomOnly || UIAnimationsRunning),
|
||||
(mZoomManager.isZoomAnimating() || UIAnimationsRunning),
|
||||
animateScroll);
|
||||
if (mNativeClass == 0) return;
|
||||
// decide which adornments to draw
|
||||
@@ -3352,7 +3324,7 @@ public class WebView extends AbsoluteLayout
|
||||
}
|
||||
} else if (mShiftIsPressed
|
||||
&& !nativePageShouldHandleShiftAndArrows()) {
|
||||
if (!animateZoom && !mZoomManager.mPreviewZoomOnly) {
|
||||
if (!mZoomManager.isZoomAnimating()) {
|
||||
extras = DRAW_EXTRAS_SELECTION;
|
||||
nativeSetSelectionRegion(mTouchSelection || mExtendSelection);
|
||||
nativeSetSelectionPointer(!mTouchSelection, mZoomManager.mInvActualScale,
|
||||
@@ -4425,79 +4397,6 @@ public class WebView extends AbsoluteLayout
|
||||
private DragTracker mDragTracker;
|
||||
private DragTrackerHandler mDragTrackerHandler;
|
||||
|
||||
private class ScaleDetectorListener implements
|
||||
ScaleGestureDetector.OnScaleGestureListener {
|
||||
|
||||
public boolean onScaleBegin(ScaleGestureDetector detector) {
|
||||
// cancel the single touch handling
|
||||
cancelTouch();
|
||||
mZoomManager.dismissZoomPicker();
|
||||
// reset the zoom overview mode so that the page won't auto grow
|
||||
mZoomManager.mInZoomOverview = false;
|
||||
// If it is in password mode, turn it off so it does not draw
|
||||
// misplaced.
|
||||
if (inEditingMode() && nativeFocusCandidateIsPassword()) {
|
||||
mWebTextView.setInPassword(false);
|
||||
}
|
||||
|
||||
mViewManager.startZoom();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onScaleEnd(ScaleGestureDetector detector) {
|
||||
if (mZoomManager.mPreviewZoomOnly) {
|
||||
mZoomManager.mPreviewZoomOnly = false;
|
||||
mAnchorX = viewToContentX((int) mZoomManager.mZoomCenterX + mScrollX);
|
||||
mAnchorY = viewToContentY((int) mZoomManager.mZoomCenterY + mScrollY);
|
||||
// don't reflow when zoom in; when zoom out, do reflow if the
|
||||
// new scale is almost minimum scale;
|
||||
boolean reflowNow = !mZoomManager.canZoomOut()
|
||||
|| (mZoomManager.mActualScale <= 0.8 * mZoomManager.mTextWrapScale);
|
||||
// force zoom after mPreviewZoomOnly is set to false so that the
|
||||
// new view size will be passed to the WebKit
|
||||
mZoomManager.refreshZoomScale(reflowNow);
|
||||
// call invalidate() to draw without zoom filter
|
||||
invalidate();
|
||||
}
|
||||
// adjust the edit text view if needed
|
||||
if (inEditingMode() && didUpdateTextViewBounds(false)
|
||||
&& nativeFocusCandidateIsPassword()) {
|
||||
// If it is a password field, start drawing the
|
||||
// WebTextView once again.
|
||||
mWebTextView.setInPassword(true);
|
||||
}
|
||||
// start a drag, TOUCH_PINCH_DRAG, can't use TOUCH_INIT_MODE as it
|
||||
// may trigger the unwanted click, can't use TOUCH_DRAG_MODE as it
|
||||
// may trigger the unwanted fling.
|
||||
mTouchMode = TOUCH_PINCH_DRAG;
|
||||
mConfirmMove = true;
|
||||
startTouch(detector.getFocusX(), detector.getFocusY(),
|
||||
mLastTouchTime);
|
||||
|
||||
mViewManager.endZoom();
|
||||
}
|
||||
|
||||
public boolean onScale(ScaleGestureDetector detector) {
|
||||
float scale = (float) (Math.round(detector.getScaleFactor()
|
||||
* mZoomManager.mActualScale * 100) / 100.0);
|
||||
if (mZoomManager.willScaleTriggerZoom(scale)) {
|
||||
mZoomManager.mPreviewZoomOnly = true;
|
||||
// limit the scale change per step
|
||||
if (scale > mZoomManager.mActualScale) {
|
||||
scale = Math.min(scale, mZoomManager.mActualScale * 1.25f);
|
||||
} else {
|
||||
scale = Math.max(scale, mZoomManager.mActualScale * 0.8f);
|
||||
}
|
||||
mZoomManager.setZoomCenter(detector.getFocusX(), detector.getFocusY());
|
||||
mZoomManager.setZoomScale(scale, false);
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hitFocusedPlugin(int contentX, int contentY) {
|
||||
if (DebugFlags.WEB_VIEW) {
|
||||
Log.v(LOGTAG, "nativeFocusIsPlugin()=" + nativeFocusIsPlugin());
|
||||
@@ -4519,6 +4418,22 @@ public class WebView extends AbsoluteLayout
|
||||
return mFullScreenHolder != null;
|
||||
}
|
||||
|
||||
void onPinchToZoomAnimationStart() {
|
||||
// cancel the single touch handling
|
||||
cancelTouch();
|
||||
onZoomAnimationStart();
|
||||
}
|
||||
|
||||
void onPinchToZoomAnimationEnd(ScaleGestureDetector detector) {
|
||||
onZoomAnimationEnd();
|
||||
// start a drag, TOUCH_PINCH_DRAG, can't use TOUCH_INIT_MODE as
|
||||
// it may trigger the unwanted click, can't use TOUCH_DRAG_MODE
|
||||
// as it may trigger the unwanted fling.
|
||||
mTouchMode = TOUCH_PINCH_DRAG;
|
||||
mConfirmMove = true;
|
||||
startTouch(detector.getFocusX(), detector.getFocusY(), mLastTouchTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
if (mNativeClass == 0 || !isClickable() || !isLongClickable()) {
|
||||
@@ -4536,32 +4451,36 @@ public class WebView extends AbsoluteLayout
|
||||
|
||||
// FIXME: we may consider to give WebKit an option to handle multi-touch
|
||||
// events later.
|
||||
if (mSupportMultiTouch && ev.getPointerCount() > 1) {
|
||||
if (mZoomManager.mMinZoomScale < mZoomManager.mMaxZoomScale) {
|
||||
mScaleDetector.onTouchEvent(ev);
|
||||
if (mScaleDetector.isInProgress()) {
|
||||
mLastTouchTime = eventTime;
|
||||
if (mZoomManager.supportsMultiTouchZoom() && ev.getPointerCount() > 1) {
|
||||
|
||||
// if the page disallows zoom, then skip multi-pointer action
|
||||
if (mZoomManager.mMinZoomScale >= mZoomManager.mMaxZoomScale) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ScaleGestureDetector detector = mZoomManager.getMultiTouchGestureDetector();
|
||||
detector.onTouchEvent(ev);
|
||||
|
||||
if (detector.isInProgress()) {
|
||||
mLastTouchTime = eventTime;
|
||||
return true;
|
||||
}
|
||||
|
||||
x = detector.getFocusX();
|
||||
y = detector.getFocusY();
|
||||
action = ev.getAction() & MotionEvent.ACTION_MASK;
|
||||
if (action == MotionEvent.ACTION_POINTER_DOWN) {
|
||||
cancelTouch();
|
||||
action = MotionEvent.ACTION_DOWN;
|
||||
} else if (action == MotionEvent.ACTION_POINTER_UP) {
|
||||
// set mLastTouchX/Y to the remaining point
|
||||
mLastTouchX = x;
|
||||
mLastTouchY = y;
|
||||
} else if (action == MotionEvent.ACTION_MOVE) {
|
||||
// negative x or y indicate it is on the edge, skip it.
|
||||
if (x < 0 || y < 0) {
|
||||
return true;
|
||||
}
|
||||
x = mScaleDetector.getFocusX();
|
||||
y = mScaleDetector.getFocusY();
|
||||
action = ev.getAction() & MotionEvent.ACTION_MASK;
|
||||
if (action == MotionEvent.ACTION_POINTER_DOWN) {
|
||||
cancelTouch();
|
||||
action = MotionEvent.ACTION_DOWN;
|
||||
} else if (action == MotionEvent.ACTION_POINTER_UP) {
|
||||
// set mLastTouchX/Y to the remaining point
|
||||
mLastTouchX = x;
|
||||
mLastTouchY = y;
|
||||
} else if (action == MotionEvent.ACTION_MOVE) {
|
||||
// negative x or y indicate it is on the edge, skip it.
|
||||
if (x < 0 || y < 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// if the page disallow zoom, skip multi-pointer action
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
action = ev.getAction();
|
||||
@@ -4625,7 +4544,6 @@ public class WebView extends AbsoluteLayout
|
||||
contentX, contentY) : false;
|
||||
}
|
||||
} else { // the normal case
|
||||
mZoomManager.mPreviewZoomOnly = false;
|
||||
mTouchMode = TOUCH_INIT_MODE;
|
||||
mDeferTouchProcess = (!inFullScreenMode()
|
||||
&& mForwardTouchEvents) ? hitFocusedPlugin(
|
||||
@@ -5922,7 +5840,7 @@ public class WebView extends AbsoluteLayout
|
||||
boolean immediate) {
|
||||
// don't scroll while in zoom animation. When it is done, we will adjust
|
||||
// the necessary components (e.g., WebTextView if it is in editing mode)
|
||||
if(mZoomManager.isZoomAnimating()) {
|
||||
if (mZoomManager.isFixedLengthAnimationInProgress()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,33 @@
|
||||
|
||||
package android.webkit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Point;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.view.ScaleGestureDetector;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* The ZoomManager is responsible for maintaining the WebView's current zoom
|
||||
* level state. It is also responsible for managing the on-screen zoom controls
|
||||
* as well as any animation of the WebView due to zooming.
|
||||
*
|
||||
* Currently, there are two methods for animating the zoom of a WebView.
|
||||
*
|
||||
* (1) The first method is triggered by startZoomAnimation(...) and is a fixed
|
||||
* length animation where the final zoom scale is known at startup. This type of
|
||||
* animation notifies webkit of the final scale BEFORE it animates. The animation
|
||||
* is then done by scaling the CANVAS incrementally based on a stepping function.
|
||||
*
|
||||
* (2) The second method is triggered by a multi-touch pinch and the new scale
|
||||
* is determined dynamically based on the user's gesture. This type of animation
|
||||
* only notifies webkit of new scale AFTER the gesture is complete. The animation
|
||||
* effect is achieved by scaling the VIEWS (both WebView and ViewManager.ChildView)
|
||||
* to the new scale in response to events related to the user's gesture.
|
||||
*/
|
||||
class ZoomManager {
|
||||
|
||||
static final String LOGTAG = "webviewZoom";
|
||||
@@ -73,9 +95,6 @@ class ZoomManager {
|
||||
|
||||
private static float MINIMUM_SCALE_INCREMENT = 0.01f;
|
||||
|
||||
// set to true temporarily during ScaleGesture triggered zoom
|
||||
boolean mPreviewZoomOnly = false;
|
||||
|
||||
// the current computed zoom scale and its inverse.
|
||||
float mActualScale;
|
||||
float mInvActualScale;
|
||||
@@ -104,6 +123,14 @@ class ZoomManager {
|
||||
private long mZoomStart;
|
||||
static final int ZOOM_ANIMATION_LENGTH = 500;
|
||||
|
||||
// whether support multi-touch
|
||||
private boolean mSupportMultiTouch;
|
||||
|
||||
// use the framework's ScaleGestureDetector to handle multi-touch
|
||||
private ScaleGestureDetector mScaleDetector;
|
||||
|
||||
private boolean mPinchToZoomAnimating = false;
|
||||
|
||||
public ZoomManager(WebView webView, CallbackProxy callbackProxy) {
|
||||
mWebView = webView;
|
||||
mCallbackProxy = callbackProxy;
|
||||
@@ -226,7 +253,7 @@ class ZoomManager {
|
||||
mInvInitialZoomScale = 1.0f / oldScale;
|
||||
mInvFinalZoomScale = 1.0f / mActualScale;
|
||||
mZoomScale = mActualScale;
|
||||
WebViewCore.pauseUpdatePicture(mWebView.getWebViewCore());
|
||||
mWebView.onFixedLengthZoomAnimationStart();
|
||||
mWebView.invalidate();
|
||||
return true;
|
||||
} else {
|
||||
@@ -235,25 +262,23 @@ class ZoomManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes and returns the relevant data needed by the WebView's drawing
|
||||
* model to animate a zoom.
|
||||
* This method is called by the WebView's drawing code when a fixed length zoom
|
||||
* animation is occurring. Its purpose is to animate the zooming of the canvas
|
||||
* to the desired scale which was specified in startZoomAnimation(...).
|
||||
*
|
||||
* This method is to be called when a zoom animation is occurring. The
|
||||
* animation begins by calling startZoomAnimation(...). The caller can
|
||||
* check to see if the animation has completed by calling isZoomAnimating().
|
||||
* A fixed length animation begins when startZoomAnimation(...) is called and
|
||||
* continues until the ZOOM_ANIMATION_LENGTH time has elapsed. During that
|
||||
* interval each time the WebView draws it calls this function which is
|
||||
* responsible for generating the animation.
|
||||
*
|
||||
* @return an array containing the values needed to animate the drawing
|
||||
* surface.
|
||||
* [0] = delta for the new scrollX position
|
||||
* [1] = delta for the new scrollY position
|
||||
* [2] = current zoom scale
|
||||
* Additionally, the WebView can check to see if such an animation is currently
|
||||
* in progress by calling isFixedLengthAnimationInProgress().
|
||||
*/
|
||||
public float[] animateZoom() {
|
||||
public void animateZoom(Canvas canvas) {
|
||||
if (mZoomScale == 0) {
|
||||
Log.w(LOGTAG, "A WebView is attempting to animate a zoom when no " +
|
||||
"zoom is in progress");
|
||||
float[] result = {0, 0, mActualScale};
|
||||
return result;
|
||||
Log.w(LOGTAG, "A WebView is attempting to perform a fixed length "
|
||||
+ "zoom animation when no zoom is in progress");
|
||||
return;
|
||||
}
|
||||
|
||||
float zoomScale;
|
||||
@@ -262,10 +287,12 @@ class ZoomManager {
|
||||
float ratio = (float) interval / ZOOM_ANIMATION_LENGTH;
|
||||
zoomScale = 1.0f / (mInvInitialZoomScale
|
||||
+ (mInvFinalZoomScale - mInvInitialZoomScale) * ratio);
|
||||
mWebView.invalidate();
|
||||
} else {
|
||||
zoomScale = mZoomScale;
|
||||
// set mZoomScale to be 0 as we have finished animating
|
||||
mZoomScale = 0;
|
||||
mWebView.onFixedLengthZoomAnimationEnd();
|
||||
}
|
||||
// calculate the intermediate scroll position. Since we need to use
|
||||
// zoomScale, we can't use the WebView's pinLocX/Y functions directly.
|
||||
@@ -281,11 +308,15 @@ class ZoomManager {
|
||||
- titleHeight, mWebView.getViewHeight(), Math.round(mWebView.getContentHeight()
|
||||
* zoomScale)) + titleHeight) + mWebView.getScrollY();
|
||||
|
||||
float[] result = {tx, ty, zoomScale};
|
||||
return result;
|
||||
canvas.translate(tx, ty);
|
||||
canvas.scale(zoomScale, zoomScale);
|
||||
}
|
||||
|
||||
public boolean isZoomAnimating() {
|
||||
return isFixedLengthAnimationInProgress() || mPinchToZoomAnimating;
|
||||
}
|
||||
|
||||
public boolean isFixedLengthAnimationInProgress() {
|
||||
return mZoomScale != 0;
|
||||
}
|
||||
|
||||
@@ -316,7 +347,7 @@ class ZoomManager {
|
||||
float oldScale = mActualScale;
|
||||
float oldInvScale = mInvActualScale;
|
||||
|
||||
if (scale != mActualScale && !mPreviewZoomOnly) {
|
||||
if (scale != mActualScale && !mPinchToZoomAnimating) {
|
||||
mCallbackProxy.onScaleChanged(mActualScale, scale);
|
||||
}
|
||||
|
||||
@@ -357,10 +388,98 @@ class ZoomManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void updateMultiTouchSupport(Context context) {
|
||||
// check the preconditions
|
||||
assert mWebView.getSettings() != null;
|
||||
|
||||
WebSettings settings = mWebView.getSettings();
|
||||
mSupportMultiTouch = context.getPackageManager().hasSystemFeature(
|
||||
PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)
|
||||
&& settings.supportZoom() && settings.getBuiltInZoomControls();
|
||||
if (mSupportMultiTouch && (mScaleDetector == null)) {
|
||||
mScaleDetector = new ScaleGestureDetector(context, new ScaleDetectorListener());
|
||||
} else if (!mSupportMultiTouch && (mScaleDetector != null)) {
|
||||
mScaleDetector = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean supportsMultiTouchZoom() {
|
||||
return mSupportMultiTouch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the caller that the ZoomManager is requesting that scale related
|
||||
* updates should not be sent to webkit. This can occur in cases where the
|
||||
* ZoomManager is performing an animation and does not want webkit to update
|
||||
* until the animation is complete.
|
||||
*
|
||||
* @return true if scale related updates should not be sent to webkit and
|
||||
* false otherwise.
|
||||
*/
|
||||
public boolean isPreventingWebkitUpdates() {
|
||||
// currently only animating a multi-touch zoom prevents updates, but
|
||||
// others can add their own conditions to this method if necessary.
|
||||
return mPinchToZoomAnimating;
|
||||
}
|
||||
|
||||
public ScaleGestureDetector getMultiTouchGestureDetector() {
|
||||
return mScaleDetector;
|
||||
}
|
||||
|
||||
private class ScaleDetectorListener implements ScaleGestureDetector.OnScaleGestureListener {
|
||||
|
||||
public boolean onScaleBegin(ScaleGestureDetector detector) {
|
||||
dismissZoomPicker();
|
||||
// reset the zoom overview mode so that the page won't auto grow
|
||||
mInZoomOverview = false;
|
||||
mWebView.mViewManager.startZoom();
|
||||
mWebView.onPinchToZoomAnimationStart();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onScale(ScaleGestureDetector detector) {
|
||||
float scale = Math.round(detector.getScaleFactor() * mActualScale * 100) * 0.01f;
|
||||
if (willScaleTriggerZoom(scale)) {
|
||||
mPinchToZoomAnimating = true;
|
||||
// limit the scale change per step
|
||||
if (scale > mActualScale) {
|
||||
scale = Math.min(scale, mActualScale * 1.25f);
|
||||
} else {
|
||||
scale = Math.max(scale, mActualScale * 0.8f);
|
||||
}
|
||||
setZoomCenter(detector.getFocusX(), detector.getFocusY());
|
||||
setZoomScale(scale, false);
|
||||
mWebView.invalidate();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onScaleEnd(ScaleGestureDetector detector) {
|
||||
if (mPinchToZoomAnimating) {
|
||||
mPinchToZoomAnimating = false;
|
||||
mWebView.setViewSizeAnchor(mWebView.viewToContentX((int) mZoomCenterX
|
||||
+ mWebView.getScrollX()), mWebView.viewToContentY((int) mZoomCenterY
|
||||
+ mWebView.getScrollY()));
|
||||
// don't reflow when zoom in; when zoom out, do reflow if the
|
||||
// new scale is almost minimum scale;
|
||||
boolean reflowNow = !canZoomOut() || (mActualScale <= 0.8 * mTextWrapScale);
|
||||
// force zoom after mPreviewZoomOnly is set to false so that the
|
||||
// new view size will be passed to the WebKit
|
||||
refreshZoomScale(reflowNow);
|
||||
// call invalidate() to draw without zoom filter
|
||||
mWebView.invalidate();
|
||||
}
|
||||
|
||||
mWebView.mViewManager.endZoom();
|
||||
mWebView.onPinchToZoomAnimationEnd(detector);
|
||||
}
|
||||
}
|
||||
|
||||
public void onSizeChanged(int w, int h, int ow, int oh) {
|
||||
// reset zoom and anchor to the top left corner of the screen
|
||||
// unless we are already zooming
|
||||
if (!isZoomAnimating()) {
|
||||
if (!isFixedLengthAnimationInProgress()) {
|
||||
int visibleTitleHeight = mWebView.getVisibleTitleHeight();
|
||||
mZoomCenterX = 0;
|
||||
mZoomCenterY = visibleTitleHeight;
|
||||
|
||||
Reference in New Issue
Block a user