Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java b/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java |
| index babdce53210f925887ae7f713c5a3738d1fd3f46..d4cafae06e7d275f0412b96f08fa378dc7c4e46c 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java |
| @@ -18,6 +18,7 @@ import android.view.animation.DecelerateInterpolator; |
| import android.view.animation.Interpolator; |
| import android.widget.FrameLayout; |
| +import org.chromium.chrome.browser.util.MathUtils; |
| import org.chromium.content.browser.ContentViewCore; |
| import org.chromium.content_public.browser.GestureStateListener; |
| @@ -31,21 +32,6 @@ import org.chromium.content_public.browser.GestureStateListener; |
| * the View slides onto and off of the screen vertically as the user scrolls upwards or |
| * downwards on the page. |
| * |
| - * VERTICAL SCROLL CALCULATIONS |
| - * To determine how close the user is to the top of the page, the View must not only be informed of |
| - * page scroll position changes, but also of changes in the viewport size (which happens as the |
| - * omnibox appears and disappears, or as the page rotates e.g.). When the viewport size gradually |
| - * shrinks, the user is most likely to be scrolling the page downwards while the omnibox comes back |
| - * into view. |
| - * |
| - * When the user first begins scrolling the page, both the scroll position and the viewport size are |
| - * summed and recorded together. This is because a pixel change in the viewport height is |
| - * equivalent to a pixel change in the content's scroll offset: |
| - * - As the user scrolls the page downward, either the viewport height will increase (as the omnibox |
| - * is slid off of the screen) or the content scroll offset will increase. |
| - * - As the user scrolls the page upward, either the viewport height will decrease (as the omnibox |
| - * is brought back onto the screen) or the content scroll offset will decrease. |
| - * |
| * As the scroll offset or the viewport height are updated via a scroll or fling, the difference |
| * from the initial value is used to determine the View's Y-translation. If a gesture is stopped, |
| * the View will be snapped back into the center of the screen or entirely off of the screen, based |
| @@ -83,9 +69,6 @@ public abstract class SwipableOverlayView extends FrameLayout { |
| // Used to determine when the layout has changed and the Viewport must be updated. |
| private int mParentHeight; |
| - // Location of the View when the current gesture was first started. |
| - private float mInitialTranslationY; |
| - |
| // Offset from the top of the page when the current gesture was first started. |
| private int mInitialOffsetY; |
| @@ -207,10 +190,19 @@ public abstract class SwipableOverlayView extends FrameLayout { |
| */ |
| private GestureStateListener createGestureStateListener() { |
| return new GestureStateListener() { |
| + // Tracks the previous event's scroll offset to determine if a scroll is up or down. |
|
gone
2017/05/08 17:01:53
javadoc syntax instead
mdjones
2017/05/08 18:13:06
Done.
|
| + private int mLastScrollOffsetY; |
| + |
| + // Location of the View when the current gesture was first started. |
| + private float mInitialTranslationY; |
| + |
| + // The initial extent of the scroll when triggered. |
| + private float mInitialExtentY; |
| + |
| @Override |
| public void onFlingStartGesture(int scrollOffsetY, int scrollExtentY) { |
| if (!isAllowedToAutoHide() || !cancelCurrentAnimation()) return; |
| - beginGesture(scrollOffsetY, scrollExtentY); |
| + resetInitialOffsets(scrollOffsetY, scrollExtentY); |
| mGestureState = GESTURE_FLINGING; |
| } |
| @@ -219,34 +211,27 @@ public abstract class SwipableOverlayView extends FrameLayout { |
| if (mGestureState != GESTURE_FLINGING) return; |
| mGestureState = GESTURE_NONE; |
| - int finalOffsetY = computeScrollDifference(scrollOffsetY, scrollExtentY); |
| updateTranslation(scrollOffsetY, scrollExtentY); |
| - boolean isScrollingDownward = finalOffsetY > 0; |
| + boolean isScrollingDownward = scrollOffsetY > mLastScrollOffsetY; |
| boolean isVisibleInitially = mInitialTranslationY < mTotalHeight; |
| float percentageVisible = 1.0f - (getTranslationY() / mTotalHeight); |
| float visibilityThreshold = isVisibleInitially |
| ? VERTICAL_FLING_HIDE_THRESHOLD : VERTICAL_FLING_SHOW_THRESHOLD; |
| boolean isVisibleEnough = percentageVisible > visibilityThreshold; |
| + boolean isNearTopOfPage = scrollOffsetY < (mTotalHeight * FULL_THRESHOLD); |
| + |
| + boolean show = (!isScrollingDownward && isVisibleEnough) || isNearTopOfPage; |
| - boolean show = !isScrollingDownward; |
| - if (isVisibleInitially) { |
| - // Check if the View was moving off-screen. |
| - boolean isHiding = getTranslationY() > mInitialTranslationY; |
| - show &= isVisibleEnough || !isHiding; |
| - } else { |
| - // When near the top of the page, there's not much room left to scroll. |
| - boolean isNearTopOfPage = finalOffsetY < (mTotalHeight * FULL_THRESHOLD); |
| - show &= isVisibleEnough || isNearTopOfPage; |
| - } |
| createVerticalSnapAnimation(show); |
| } |
| @Override |
| public void onScrollStarted(int scrollOffsetY, int scrollExtentY) { |
| if (!isAllowedToAutoHide() || !cancelCurrentAnimation()) return; |
| - beginGesture(scrollOffsetY, scrollExtentY); |
| + resetInitialOffsets(scrollOffsetY, scrollExtentY); |
| + mLastScrollOffsetY = scrollOffsetY; |
| mGestureState = GESTURE_SCROLLING; |
| } |
| @@ -255,10 +240,9 @@ public abstract class SwipableOverlayView extends FrameLayout { |
| if (mGestureState != GESTURE_SCROLLING) return; |
| mGestureState = GESTURE_NONE; |
| - int finalOffsetY = computeScrollDifference(scrollOffsetY, scrollExtentY); |
| updateTranslation(scrollOffsetY, scrollExtentY); |
| - boolean isNearTopOfPage = finalOffsetY < (mTotalHeight * FULL_THRESHOLD); |
| + boolean isNearTopOfPage = scrollOffsetY < (mTotalHeight * FULL_THRESHOLD); |
| boolean isVisibleEnough = getTranslationY() < mTotalHeight * FULL_THRESHOLD; |
| createVerticalSnapAnimation(isNearTopOfPage || isVisibleEnough); |
| } |
| @@ -267,15 +251,31 @@ public abstract class SwipableOverlayView extends FrameLayout { |
| public void onScrollOffsetOrExtentChanged(int scrollOffsetY, int scrollExtentY) { |
| // This function is called for both fling and scrolls. |
| if (mGestureState == GESTURE_NONE || !cancelCurrentAnimation()) return; |
| + mLastScrollOffsetY = scrollOffsetY; |
| updateTranslation(scrollOffsetY, scrollExtentY); |
| } |
| private void updateTranslation(int scrollOffsetY, int scrollExtentY) { |
| - float translation = mInitialTranslationY |
| - + computeScrollDifference(scrollOffsetY, scrollExtentY); |
| - translation = Math.max(0.0f, Math.min(mTotalHeight, translation)); |
| + float scrollDiff = |
| + (scrollOffsetY - mInitialOffsetY) + (scrollExtentY - mInitialExtentY); |
| + float translation = |
| + MathUtils.clamp(mInitialTranslationY + scrollDiff, mTotalHeight, 0); |
| + |
| + // If the container has reached the completely shown position, reset the initial |
| + // scroll so any movement will start hiding it again. |
| + if (translation <= 0f) resetInitialOffsets(scrollOffsetY, scrollExtentY); |
| + |
| setTranslationY(translation); |
| } |
| + |
| + /** |
| + * Records the conditions of the page to handle scrolls appropriately. |
| + */ |
| + private void resetInitialOffsets(int scrollOffsetY, int scrollExtentY) { |
| + mInitialOffsetY = scrollOffsetY; |
| + mInitialExtentY = scrollExtentY; |
| + mInitialTranslationY = getTranslationY(); |
| + } |
| }; |
| } |
| @@ -317,10 +317,6 @@ public abstract class SwipableOverlayView extends FrameLayout { |
| mCurrentAnimation.start(); |
| } |
| - private int computeScrollDifference(int scrollOffsetY, int scrollExtentY) { |
| - return scrollOffsetY + scrollExtentY - mInitialOffsetY; |
| - } |
| - |
| /** |
| * Creates an AnimatorListenerAdapter that cleans up after an animation is completed. |
| * @return {@link AnimatorListenerAdapter} to use for animations. |
| @@ -337,16 +333,6 @@ public abstract class SwipableOverlayView extends FrameLayout { |
| } |
| /** |
| - * Records the conditions of the page when a gesture is initiated. |
| - */ |
| - private void beginGesture(int scrollOffsetY, int scrollExtentY) { |
| - mInitialTranslationY = getTranslationY(); |
| - boolean isInitiallyVisible = mInitialTranslationY < mTotalHeight; |
| - int startingY = isInitiallyVisible ? scrollOffsetY : Math.min(scrollOffsetY, mTotalHeight); |
| - mInitialOffsetY = startingY + scrollExtentY; |
| - } |
| - |
| - /** |
| * Cancels the current animation, unless the View is coming onto the screen for the first time. |
| * @return True if the animation was canceled or wasn't running, false otherwise. |
| */ |