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. |
*/ |