diff options
Diffstat (limited to 'core/java/android/webkit/WebView.java')
| -rw-r--r-- | core/java/android/webkit/WebView.java | 193 |
1 files changed, 150 insertions, 43 deletions
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 052de972a66e..0deb45aff8cd 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -39,8 +39,8 @@ import android.graphics.RectF; import android.graphics.Region; import android.graphics.Shader; import android.graphics.drawable.Drawable; -import android.net.Uri; import android.net.http.SslCertificate; +import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -79,7 +79,7 @@ import android.widget.CheckedTextView; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.ListView; -import android.widget.Scroller; +import android.widget.OverScroller; import android.widget.Toast; import android.widget.ZoomButtonsController; import android.widget.ZoomControls; @@ -92,8 +92,8 @@ import java.io.FileOutputStream; import java.io.IOException; import java.net.URLDecoder; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; +import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -557,7 +557,10 @@ public class WebView extends AbsoluteLayout // time for the longest scroll animation private static final int MAX_DURATION = 750; // milliseconds private static final int SLIDE_TITLE_DURATION = 500; // milliseconds - private Scroller mScroller; + private OverScroller mScroller; + private boolean mInOverScrollMode = false; + private static Paint mOverScrollBackground; + private static Paint mOverScrollBorder; private boolean mWrapContent; private static final int MOTIONLESS_FALSE = 0; @@ -943,7 +946,7 @@ public class WebView extends AbsoluteLayout mViewManager = new ViewManager(this); mWebViewCore = new WebViewCore(context, this, mCallbackProxy, javascriptInterfaces); mDatabase = WebViewDatabase.getInstance(context); - mScroller = new Scroller(context); + mScroller = new OverScroller(context); updateMultiTouchSupport(context); } @@ -983,6 +986,7 @@ public class WebView extends AbsoluteLayout setFocusableInTouchMode(true); setClickable(true); setLongClickable(true); + setOverscrollMode(OVERSCROLL_NEVER); final ViewConfiguration configuration = ViewConfiguration.get(getContext()); int slop = configuration.getScaledTouchSlop(); @@ -1146,7 +1150,8 @@ public class WebView extends AbsoluteLayout * Return the amount of the titlebarview (if any) that is visible */ private int getVisibleTitleHeight() { - return Math.max(getTitleHeight() - mScrollY, 0); + // need to restrict mScrollY due to over scroll + return Math.max(getTitleHeight() - Math.max(0, mScrollY), 0); } /* @@ -1786,7 +1791,7 @@ public class WebView extends AbsoluteLayout } nativeClearCursor(); // start next trackball movement from page edge if (bottom) { - return pinScrollTo(mScrollX, computeVerticalScrollRange(), true, 0); + return pinScrollTo(mScrollX, computeRealVerticalScrollRange(), true, 0); } // Page down. int h = getHeight(); @@ -2016,13 +2021,15 @@ public class WebView extends AbsoluteLayout // Expects x in view coordinates private int pinLocX(int x) { - return pinLoc(x, getViewWidth(), computeHorizontalScrollRange()); + if (mInOverScrollMode) return x; + return pinLoc(x, getViewWidth(), computeRealHorizontalScrollRange()); } // Expects y in view coordinates private int pinLocY(int y) { + if (mInOverScrollMode) return y; return pinLoc(y, getViewHeightWithTitle(), - computeVerticalScrollRange() + getTitleHeight()); + computeRealVerticalScrollRange() + getTitleHeight()); } /** @@ -2334,7 +2341,7 @@ public class WebView extends AbsoluteLayout // Sets r to be our visible rectangle in content coordinates private void calcOurContentVisibleRect(Rect r) { calcOurVisibleRect(r); - // pin the rect to the bounds of the content + // since we might overscroll, pin the rect to the bounds of the content r.left = Math.max(viewToContentX(r.left), 0); // viewToContentY will remove the total height of the title bar. Add // the visible height back in to account for the fact that if the title @@ -2415,8 +2422,7 @@ public class WebView extends AbsoluteLayout return false; } - @Override - protected int computeHorizontalScrollRange() { + private int computeRealHorizontalScrollRange() { if (mDrawHistory) { return mHistoryWidth; } else if (mHorizontalScrollBarMode == SCROLLBAR_ALWAYSOFF @@ -2430,7 +2436,27 @@ public class WebView extends AbsoluteLayout } @Override - protected int computeVerticalScrollRange() { + protected int computeHorizontalScrollRange() { + int range = computeRealHorizontalScrollRange(); + + // Adjust reported range if overscrolled to compress the scroll bars + final int scrollX = mScrollX; + final int overscrollRight = computeMaxScrollX(); + if (scrollX < 0) { + range -= scrollX; + } else if (scrollX > overscrollRight) { + range += scrollX - overscrollRight; + } + + return range; + } + + @Override + protected int computeHorizontalScrollOffset() { + return Math.max(mScrollX, 0); + } + + private int computeRealVerticalScrollRange() { if (mDrawHistory) { return mHistoryHeight; } else if (mVerticalScrollBarMode == SCROLLBAR_ALWAYSOFF @@ -2444,6 +2470,22 @@ public class WebView extends AbsoluteLayout } @Override + protected int computeVerticalScrollRange() { + int range = computeRealVerticalScrollRange(); + + // Adjust reported range if overscrolled to compress the scroll bars + final int scrollY = mScrollY; + final int overscrollBottom = computeMaxScrollY(); + if (scrollY < 0) { + range -= scrollY; + } else if (scrollY > overscrollBottom) { + range += scrollY - overscrollBottom; + } + + return range; + } + + @Override protected int computeVerticalScrollOffset() { return Math.max(mScrollY - getTitleHeight(), 0); } @@ -2462,6 +2504,23 @@ public class WebView extends AbsoluteLayout scrollBar.draw(canvas); } + @Override + protected void onOverscrolled(int scrollX, int scrollY, boolean clampedX, + boolean clampedY) { + mInOverScrollMode = false; + int maxX = computeMaxScrollX(); + if (maxX == 0) { + // do not over scroll x if the page just fits the screen + scrollX = pinLocX(scrollX); + } else if (scrollX < 0 || scrollX > maxX) { + mInOverScrollMode = true; + } + if (scrollY < 0 || scrollY > computeMaxScrollY()) { + mInOverScrollMode = true; + } + super.scrollTo(scrollX, scrollY); + } + /** * Get the url for the current page. This is not always the same as the url * passed to WebViewClient.onPageStarted because although the load for @@ -2815,11 +2874,14 @@ public class WebView extends AbsoluteLayout if (mScroller.computeScrollOffset()) { int oldX = mScrollX; int oldY = mScrollY; - mScrollX = mScroller.getCurrX(); - mScrollY = mScroller.getCurrY(); + int x = mScroller.getCurrX(); + int y = mScroller.getCurrY(); postInvalidate(); // So we draw again - if (oldX != mScrollX || oldY != mScrollY) { - onScrollChanged(mScrollX, mScrollY, oldX, oldY); + + if (oldX != x || oldY != y) { + overscrollBy(x - oldX, y - oldY, oldX, oldY, + computeMaxScrollX(), computeMaxScrollY(), + getViewWidth() / 3, getViewHeight() / 3, false); } } else { super.computeScroll(); @@ -3230,8 +3292,13 @@ public class WebView extends AbsoluteLayout protected boolean drawChild(Canvas canvas, View child, long drawingTime) { if (child == mTitleBar) { // When drawing the title bar, move it horizontally to always show - // at the top of the WebView. + // at the top of the WebView. While overscroll, stick the title bar + // on the top otherwise we may have two during loading, one is drawn + // here, another is drawn by the Browser. mTitleBar.offsetLeftAndRight(mScrollX - mTitleBar.getLeft()); + if (mScrollY <= 0) { + mTitleBar.offsetTopAndBottom(mScrollY - mTitleBar.getTop()); + } } return super.drawChild(canvas, child, drawingTime); } @@ -3267,6 +3334,36 @@ public class WebView extends AbsoluteLayout } int saveCount = canvas.save(); + if (mInOverScrollMode && !getSettings() + .getUseWebViewBackgroundForOverscrollBackground()) { + if (mOverScrollBackground == null) { + mOverScrollBackground = new Paint(); + Bitmap bm = BitmapFactory.decodeResource( + mContext.getResources(), + com.android.internal.R.drawable.status_bar_background); + mOverScrollBackground.setShader(new BitmapShader(bm, + Shader.TileMode.REPEAT, Shader.TileMode.REPEAT)); + mOverScrollBorder = new Paint(); + mOverScrollBorder.setStyle(Paint.Style.STROKE); + mOverScrollBorder.setStrokeWidth(0); + mOverScrollBorder.setColor(0xffbbbbbb); + } + + int top = getTitleHeight(); + int right = computeRealHorizontalScrollRange(); + int bottom = top + computeRealVerticalScrollRange(); + // first draw the background and anchor to the top of the view + canvas.save(); + canvas.translate(mScrollX, mScrollY); + canvas.clipRect(-mScrollX, top - mScrollY, right - mScrollX, bottom + - mScrollY, Region.Op.DIFFERENCE); + canvas.drawPaint(mOverScrollBackground); + canvas.restore(); + // then draw the border + canvas.drawRect(-1, top - 1, right, bottom, mOverScrollBorder); + // next clip the region for the content + canvas.clipRect(0, top, right, bottom); + } if (mTitleBar != null) { canvas.translate(0, (int) mTitleBar.getHeight()); } @@ -4405,12 +4502,14 @@ public class WebView extends AbsoluteLayout @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); - sendOurVisibleRect(); - // update WebKit if visible title bar height changed. The logic is same - // as getVisibleTitleHeight. - int titleHeight = getTitleHeight(); - if (Math.max(titleHeight - t, 0) != Math.max(titleHeight - oldt, 0)) { - sendViewSizeZoom(); + if (!mInOverScrollMode) { + sendOurVisibleRect(); + // update WebKit if visible title bar height changed. The logic is same + // as getVisibleTitleHeight. + int titleHeight = getTitleHeight(); + if (Math.max(titleHeight - t, 0) != Math.max(titleHeight - oldt, 0)) { + sendViewSizeZoom(); + } } } @@ -4480,7 +4579,7 @@ public class WebView extends AbsoluteLayout public DragTrackerHandler(float x, float y, DragTracker proxy) { mProxy = proxy; - int docBottom = computeVerticalScrollRange() + getTitleHeight(); + int docBottom = computeRealVerticalScrollRange() + getTitleHeight(); int viewTop = getScrollY(); int viewBottom = viewTop + getHeight(); @@ -4493,7 +4592,7 @@ public class WebView extends AbsoluteLayout " up/down= " + mMinDY + " " + mMaxDY); } - int docRight = computeHorizontalScrollRange(); + int docRight = computeRealHorizontalScrollRange(); int viewLeft = getScrollX(); int viewRight = viewLeft + getWidth(); mStartX = x; @@ -5001,18 +5100,6 @@ public class WebView extends AbsoluteLayout } // do pan - int newScrollX = pinLocX(mScrollX + deltaX); - int newDeltaX = newScrollX - mScrollX; - if (deltaX != newDeltaX) { - deltaX = newDeltaX; - fDeltaX = (float) newDeltaX; - } - int newScrollY = pinLocY(mScrollY + deltaY); - int newDeltaY = newScrollY - mScrollY; - if (deltaY != newDeltaY) { - deltaY = newDeltaY; - fDeltaY = (float) newDeltaY; - } boolean done = false; boolean keepScrollBarsVisible = false; if (Math.abs(fDeltaX) < 1.0f && Math.abs(fDeltaY) < 1.0f) { @@ -5196,6 +5283,12 @@ public class WebView extends AbsoluteLayout mHeldMotionless = MOTIONLESS_IGNORE; doFling(); break; + } else { + if (mScroller.springback(mScrollX, mScrollY, 0, + computeMaxScrollX(), 0, + computeMaxScrollY())) { + invalidate(); + } } // redraw in high-quality, as we're done dragging mHeldMotionless = MOTIONLESS_TRUE; @@ -5215,6 +5308,8 @@ public class WebView extends AbsoluteLayout } case MotionEvent.ACTION_CANCEL: { if (mTouchMode == TOUCH_DRAG_MODE) { + mScroller.springback(mScrollX, mScrollY, 0, + computeMaxScrollX(), 0, computeMaxScrollY()); invalidate(); } cancelWebCoreTouchEvent(contentX, contentY, false); @@ -5278,7 +5373,9 @@ public class WebView extends AbsoluteLayout private void doDrag(int deltaX, int deltaY) { if ((deltaX | deltaY) != 0) { - scrollBy(deltaX, deltaY); + overscrollBy(deltaX, deltaY, mScrollX, mScrollY, + computeMaxScrollX(), computeMaxScrollY(), + getViewWidth() / 3, getViewHeight() / 3, true); } if (!getSettings().getBuiltInZoomControls()) { boolean showPlusMinus = mMinZoomScale < mMaxZoomScale; @@ -5626,17 +5723,17 @@ public class WebView extends AbsoluteLayout } private int computeMaxScrollX() { - return Math.max(computeHorizontalScrollRange() - getViewWidth(), 0); + return Math.max(computeRealHorizontalScrollRange() - getViewWidth(), 0); } private int computeMaxScrollY() { - return Math.max(computeVerticalScrollRange() + getTitleHeight() + return Math.max(computeRealVerticalScrollRange() + getTitleHeight() - getViewHeightWithTitle(), 0); } public void flingScroll(int vx, int vy) { mScroller.fling(mScrollX, mScrollY, vx, vy, 0, computeMaxScrollX(), 0, - computeMaxScrollY()); + computeMaxScrollY(), getViewWidth() / 3, getViewHeight() / 3); invalidate(); } @@ -5666,6 +5763,10 @@ public class WebView extends AbsoluteLayout if ((maxX == 0 && vy == 0) || (maxY == 0 && vx == 0)) { WebViewCore.resumePriority(); WebViewCore.resumeUpdatePicture(mWebViewCore); + if (mScroller.springback(mScrollX, mScrollY, 0, computeMaxScrollX(), + 0, computeMaxScrollY())) { + invalidate(); + } return; } float currentVelocity = mScroller.getCurrVelocity(); @@ -5693,7 +5794,9 @@ public class WebView extends AbsoluteLayout mLastVelY = vy; mLastVelocity = (float) Math.hypot(vx, vy); - mScroller.fling(mScrollX, mScrollY, -vx, -vy, 0, maxX, 0, maxY); + // no horizontal overscroll if the content just fits + mScroller.fling(mScrollX, mScrollY, -vx, -vy, 0, maxX, 0, maxY, + maxX == 0 ? 0 : getViewWidth() / 3, getViewHeight() / 3); // TODO: duration is calculated based on velocity, if the range is // small, the animation will stop before duration is up. We may // want to calculate how long the animation is going to run to precisely @@ -6747,6 +6850,10 @@ public class WebView extends AbsoluteLayout case MotionEvent.ACTION_CANCEL: if (mDeferTouchMode == TOUCH_DRAG_MODE) { // no fling in defer process + mScroller.springback(mScrollX, mScrollY, 0, + computeMaxScrollX(), 0, + computeMaxScrollY()); + invalidate(); WebViewCore.resumePriority(); WebViewCore.resumeUpdatePicture(mWebViewCore); } |
