Commit e5ffe711 authored by Sinan Sahin's avatar Sinan Sahin Committed by Commit Bot

[Offline indicator v2] Add Java browser controls height animations

Currently, the browser controls height change animations are driven in
browser_controls_offset_manager.cc if we have web contents. For other
cases, we simply don't animate the browser controls.

This CL adds animations for the browser controls for cases where we
can't drive the animation in native, e.g. NTP, tab switcher. These
browser side animations are run in ChromeFullscreenManager, similar to
the existing browser-driven-show-animation.

We will animate the changing margins and layouts in a separate CL.

Bug: 1075640
Change-Id: I4a90479e6ff6a350b72bfb5a83fc9c10e6aaf133
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2247244
Commit-Queue: Sinan Sahin <sinansahin@google.com>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Cr-Commit-Position: refs/heads/master@{#781398}
parent f907b70b
...@@ -64,10 +64,11 @@ public class ChromeFullscreenManager implements ActivityStateListener, ...@@ -64,10 +64,11 @@ public class ChromeFullscreenManager implements ActivityStateListener,
private static final long ACTIVITY_RETURN_SHOW_REQUEST_DELAY_MS = 100; private static final long ACTIVITY_RETURN_SHOW_REQUEST_DELAY_MS = 100;
/** /**
* Maximum duration for the control container slide-in animation. Note that this value matches * Maximum duration for the control container slide-in animation and the duration for the
* the one in browser_controls_offset_manager.cc. * browser controls height change animation. Note that this value matches the one in
* browser_controls_offset_manager.cc.
*/ */
private static final int MAX_CONTROLS_ANIMATION_DURATION_MS = 200; private static final int CONTROLS_ANIMATION_DURATION_MS = 200;
private final Activity mActivity; private final Activity mActivity;
private final BrowserStateBrowserControlsVisibilityDelegate mBrowserVisibilityDelegate; private final BrowserStateBrowserControlsVisibilityDelegate mBrowserVisibilityDelegate;
...@@ -113,7 +114,7 @@ public class ChromeFullscreenManager implements ActivityStateListener, ...@@ -113,7 +114,7 @@ public class ChromeFullscreenManager implements ActivityStateListener,
@Nullable @Nullable
private Tab mTab; private Tab mTab;
/** The animator for slide-in animation on the Android controls. */ /** The animator for the Android browser controls. */
private ValueAnimator mControlsAnimator; private ValueAnimator mControlsAnimator;
/** /**
...@@ -237,7 +238,7 @@ public class ChromeFullscreenManager implements ActivityStateListener, ...@@ -237,7 +238,7 @@ public class ChromeFullscreenManager implements ActivityStateListener,
public void onBrowserControlsOffsetChanged(Tab tab, int topControlsOffset, public void onBrowserControlsOffsetChanged(Tab tab, int topControlsOffset,
int bottomControlsOffset, int contentOffset, int topControlsMinHeightOffset, int bottomControlsOffset, int contentOffset, int topControlsMinHeightOffset,
int bottomControlsMinHeightOffset) { int bottomControlsMinHeightOffset) {
if (tab == getTab() && tab.isUserInteractable()) { if (tab == getTab() && tab.isUserInteractable() && !tab.isNativePage()) {
onOffsetsChanged(topControlsOffset, bottomControlsOffset, contentOffset, onOffsetsChanged(topControlsOffset, bottomControlsOffset, contentOffset,
topControlsMinHeightOffset, bottomControlsMinHeightOffset); topControlsMinHeightOffset, bottomControlsMinHeightOffset);
} }
...@@ -374,8 +375,20 @@ public class ChromeFullscreenManager implements ActivityStateListener, ...@@ -374,8 +375,20 @@ public class ChromeFullscreenManager implements ActivityStateListener,
&& mTopControlsMinHeight == topControlsMinHeight) { && mTopControlsMinHeight == topControlsMinHeight) {
return; return;
} }
final int oldTopHeight = mTopControlContainerHeight;
final int oldTopMinHeight = mTopControlsMinHeight;
mTopControlContainerHeight = topControlsHeight; mTopControlContainerHeight = topControlsHeight;
mTopControlsMinHeight = topControlsMinHeight; mTopControlsMinHeight = topControlsMinHeight;
if (!canAnimateNativeBrowserControls()) {
if (shouldAnimateBrowserControlsHeightChanges()) {
runBrowserDrivenTopControlsHeightChangeAnimation(oldTopHeight, oldTopMinHeight);
} else {
showAndroidControls(false);
}
}
for (BrowserControlsStateProvider.Observer obs : mControlsObservers) { for (BrowserControlsStateProvider.Observer obs : mControlsObservers) {
obs.onTopControlsHeightChanged(mTopControlContainerHeight, mTopControlsMinHeight); obs.onTopControlsHeightChanged(mTopControlContainerHeight, mTopControlsMinHeight);
} }
...@@ -596,15 +609,7 @@ public class ChromeFullscreenManager implements ActivityStateListener, ...@@ -596,15 +609,7 @@ public class ChromeFullscreenManager implements ActivityStateListener,
if (mHidingTokenHolder.hasTokens()) { if (mHidingTokenHolder.hasTokens()) {
return false; return false;
} }
if (offsetOverridden()) return true;
Tab tab = getTab();
if (tab != null) {
if (tab.isInitialized()) {
if (offsetOverridden()) return true;
} else {
assert false : "Accessing a destroyed tab, setTab should have been called";
}
}
boolean showControls = !BrowserControlsUtils.drawControlsAsTexture(this); boolean showControls = !BrowserControlsUtils.drawControlsAsTexture(this);
ViewGroup contentView = getContentView(); ViewGroup contentView = getContentView();
...@@ -884,7 +889,7 @@ public class ChromeFullscreenManager implements ActivityStateListener, ...@@ -884,7 +889,7 @@ public class ChromeFullscreenManager implements ActivityStateListener,
// Set animation start value to current renderer controls offset. // Set animation start value to current renderer controls offset.
mControlsAnimator = ValueAnimator.ofInt(topControlOffset, 0); mControlsAnimator = ValueAnimator.ofInt(topControlOffset, 0);
mControlsAnimator.setDuration( mControlsAnimator.setDuration(
(long) Math.abs(hiddenRatio * MAX_CONTROLS_ANIMATION_DURATION_MS)); (long) Math.abs(hiddenRatio * CONTROLS_ANIMATION_DURATION_MS));
mControlsAnimator.addListener(new AnimatorListenerAdapter() { mControlsAnimator.addListener(new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
...@@ -904,6 +909,49 @@ public class ChromeFullscreenManager implements ActivityStateListener, ...@@ -904,6 +909,49 @@ public class ChromeFullscreenManager implements ActivityStateListener,
mControlsAnimator.start(); mControlsAnimator.start();
} }
private void runBrowserDrivenTopControlsHeightChangeAnimation(
int oldTopControlsHeight, int oldTopControlsMinHeight) {
if (mControlsAnimator != null) return;
assert getContentOffset()
== oldTopControlsHeight
: "Height change animations are implemented for fully shown controls only!";
setOffsetOverridden(true);
final int newTopControlsHeight = getTopControlsHeight();
final int newTopControlsMinHeight = getTopControlsMinHeight();
mControlsAnimator = ValueAnimator.ofFloat(0.f, 1.f);
mControlsAnimator.addUpdateListener((animator) -> {
final float topControlsMinHeightOffset = oldTopControlsMinHeight
+ (float) animator.getAnimatedValue()
* (newTopControlsMinHeight - oldTopControlsMinHeight);
final float topContentOffset = oldTopControlsHeight
+ (float) animator.getAnimatedValue()
* (newTopControlsHeight - oldTopControlsHeight);
final float topControlsOffset = topContentOffset - newTopControlsHeight;
updateFullscreenManagerOffsets(false, (int) topControlsOffset, getBottomControlOffset(),
(int) topContentOffset, (int) topControlsMinHeightOffset,
getBottomControlsMinHeightOffset());
});
mControlsAnimator.setDuration(CONTROLS_ANIMATION_DURATION_MS);
mControlsAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
updateFullscreenManagerOffsets(false, 0, 0, getTopControlsHeight(),
getTopControlsMinHeight(), getBottomControlsMinHeight());
mControlsAnimator = null;
}
});
mControlsAnimator.start();
}
private boolean canAnimateNativeBrowserControls() {
final Tab tab = getTab();
return tab != null && tab.isUserInteractable() && !tab.isNativePage();
}
// VR-related methods to make this class test-friendly. These are overridden in unit tests. // VR-related methods to make this class test-friendly. These are overridden in unit tests.
protected boolean isInVr() { protected boolean isInVr() {
...@@ -957,4 +1005,14 @@ public class ChromeFullscreenManager implements ActivityStateListener, ...@@ -957,4 +1005,14 @@ public class ChromeFullscreenManager implements ActivityStateListener,
TabModelSelectorTabObserver getTabControlsObserverForTesting() { TabModelSelectorTabObserver getTabControlsObserverForTesting() {
return mTabControlsObserver; return mTabControlsObserver;
} }
@VisibleForTesting
ValueAnimator getControlsAnimatorForTesting() {
return mControlsAnimator;
}
@VisibleForTesting
int getControlsAnimationDurationMsForTesting() {
return CONTROLS_ANIMATION_DURATION_MS;
}
} }
...@@ -36,7 +36,7 @@ class StatusIndicatorMediator ...@@ -36,7 +36,7 @@ class StatusIndicatorMediator
private HashSet<StatusIndicatorCoordinator.StatusIndicatorObserver> mObservers = private HashSet<StatusIndicatorCoordinator.StatusIndicatorObserver> mObservers =
new HashSet<>(); new HashSet<>();
private Supplier<Integer> mStatusBarWithoutIndicatorColorSupplier; private Supplier<Integer> mStatusBarWithoutIndicatorColorSupplier;
private Runnable mOnCompositorShowAnimationEnd; private Runnable mOnShowAnimationEnd;
private Supplier<Boolean> mCanAnimateNativeBrowserControls; private Supplier<Boolean> mCanAnimateNativeBrowserControls;
private Callback<Runnable> mInvalidateCompositorView; private Callback<Runnable> mInvalidateCompositorView;
private Runnable mRequestLayout; private Runnable mRequestLayout;
...@@ -81,10 +81,6 @@ class StatusIndicatorMediator ...@@ -81,10 +81,6 @@ class StatusIndicatorMediator
@Override @Override
public void onControlsOffsetChanged(int topOffset, int topControlsMinHeightOffset, public void onControlsOffsetChanged(int topOffset, int topControlsMinHeightOffset,
int bottomOffset, int bottomControlsMinHeightOffset, boolean needsAnimate) { int bottomOffset, int bottomControlsMinHeightOffset, boolean needsAnimate) {
// If we aren't animating the browser controls in cc, we shouldn't care about the offsets
// we get.
if (!mCanAnimateNativeBrowserControls.get()) return;
onOffsetChanged(topControlsMinHeightOffset); onOffsetChanged(topControlsMinHeightOffset);
} }
...@@ -149,7 +145,7 @@ class StatusIndicatorMediator ...@@ -149,7 +145,7 @@ class StatusIndicatorMediator
mModel.set(StatusIndicatorProperties.TEXT_COLOR, textColor); mModel.set(StatusIndicatorProperties.TEXT_COLOR, textColor);
mModel.set(StatusIndicatorProperties.ICON_TINT, iconTint); mModel.set(StatusIndicatorProperties.ICON_TINT, iconTint);
mModel.set(StatusIndicatorProperties.ANDROID_VIEW_VISIBILITY, View.INVISIBLE); mModel.set(StatusIndicatorProperties.ANDROID_VIEW_VISIBILITY, View.INVISIBLE);
mOnCompositorShowAnimationEnd = () -> animateTextFadeIn(); mOnShowAnimationEnd = () -> animateTextFadeIn();
}; };
final int statusBarColor = mStatusBarWithoutIndicatorColorSupplier.get(); final int statusBarColor = mStatusBarWithoutIndicatorColorSupplier.get();
...@@ -365,31 +361,35 @@ class StatusIndicatorMediator ...@@ -365,31 +361,35 @@ class StatusIndicatorMediator
mBrowserControlsStateProvider.addObserver(this); mBrowserControlsStateProvider.addObserver(this);
} }
// If the browser controls won't be animating, we can pretend that the animation ended.
if (!mCanAnimateNativeBrowserControls.get()) {
onOffsetChanged(mIndicatorHeight);
}
notifyHeightChange(mIndicatorHeight); notifyHeightChange(mIndicatorHeight);
} }
private void onOffsetChanged(int topControlsMinHeightOffset) { private void onOffsetChanged(int topControlsMinHeightOffset) {
final boolean compositedVisible = topControlsMinHeightOffset > 0; final boolean indicatorVisible = topControlsMinHeightOffset > 0;
// Composited view should be visible if we have a positive top min-height offset, or current // Composited view should be visible if we have a positive top min-height offset (or current
// min-height. // min-height) and we're running the animations in native.
mModel.set(StatusIndicatorProperties.COMPOSITED_VIEW_VISIBLE, compositedVisible); mModel.set(StatusIndicatorProperties.COMPOSITED_VIEW_VISIBLE,
indicatorVisible && mCanAnimateNativeBrowserControls.get());
mModel.set(StatusIndicatorProperties.CURRENT_VISIBLE_HEIGHT, topControlsMinHeightOffset);
final boolean isCompletelyShown = topControlsMinHeightOffset == mIndicatorHeight; final boolean isCompletelyShown = topControlsMinHeightOffset == mIndicatorHeight;
// Android view should only be visible when the indicator is fully shown. // If we're running the animations in native, the Android view should only be visible when
// the indicator is fully shown. Otherwise, the Android view will be visible if it's within
// screen boundaries.
mModel.set(StatusIndicatorProperties.ANDROID_VIEW_VISIBILITY, mModel.set(StatusIndicatorProperties.ANDROID_VIEW_VISIBILITY,
mIsHiding ? View.GONE : (isCompletelyShown ? View.VISIBLE : View.INVISIBLE)); mIsHiding && (mCanAnimateNativeBrowserControls.get() || !indicatorVisible)
? View.GONE
if (mOnCompositorShowAnimationEnd != null && isCompletelyShown) { : (isCompletelyShown || !mCanAnimateNativeBrowserControls.get()
mOnCompositorShowAnimationEnd.run(); ? View.VISIBLE
mOnCompositorShowAnimationEnd = null; : View.INVISIBLE));
if (mOnShowAnimationEnd != null && isCompletelyShown) {
mOnShowAnimationEnd.run();
mOnShowAnimationEnd = null;
} }
final boolean doneHiding = !compositedVisible && mIsHiding; final boolean doneHiding = !indicatorVisible && mIsHiding;
if (doneHiding) { if (doneHiding) {
mBrowserControlsStateProvider.removeObserver(this); mBrowserControlsStateProvider.removeObserver(this);
mIsHiding = false; mIsHiding = false;
......
...@@ -26,19 +26,30 @@ class StatusIndicatorProperties { ...@@ -26,19 +26,30 @@ class StatusIndicatorProperties {
static final PropertyModel.WritableBooleanPropertyKey COMPOSITED_VIEW_VISIBLE = static final PropertyModel.WritableBooleanPropertyKey COMPOSITED_VIEW_VISIBLE =
new PropertyModel.WritableBooleanPropertyKey(); new PropertyModel.WritableBooleanPropertyKey();
/** Color of the widget's background. */
static final PropertyModel.WritableIntPropertyKey BACKGROUND_COLOR = static final PropertyModel.WritableIntPropertyKey BACKGROUND_COLOR =
new PropertyModel.WritableIntPropertyKey(); new PropertyModel.WritableIntPropertyKey();
/** Alpha of the text, including the icon. */
static final PropertyModel.WritableFloatPropertyKey TEXT_ALPHA = static final PropertyModel.WritableFloatPropertyKey TEXT_ALPHA =
new PropertyModel.WritableFloatPropertyKey(); new PropertyModel.WritableFloatPropertyKey();
/** Color of the status text. */
static final PropertyModel.WritableIntPropertyKey TEXT_COLOR = static final PropertyModel.WritableIntPropertyKey TEXT_COLOR =
new PropertyModel.WritableIntPropertyKey(); new PropertyModel.WritableIntPropertyKey();
/** Tint of the status icon. */
static final PropertyModel.WritableIntPropertyKey ICON_TINT = static final PropertyModel.WritableIntPropertyKey ICON_TINT =
new PropertyModel.WritableIntPropertyKey(); new PropertyModel.WritableIntPropertyKey();
static final PropertyKey[] ALL_KEYS = /**
new PropertyKey[] {STATUS_TEXT, STATUS_ICON, ANDROID_VIEW_VISIBILITY, * Current visible height of the Android view. This is used when there is a Java height
COMPOSITED_VIEW_VISIBLE, BACKGROUND_COLOR, TEXT_ALPHA, TEXT_COLOR, ICON_TINT}; * animation running rather than a native one.
*/
static final PropertyModel.WritableIntPropertyKey CURRENT_VISIBLE_HEIGHT =
new PropertyModel.WritableIntPropertyKey();
static final PropertyKey[] ALL_KEYS = new PropertyKey[] {STATUS_TEXT, STATUS_ICON,
ANDROID_VIEW_VISIBILITY, COMPOSITED_VIEW_VISIBLE, BACKGROUND_COLOR, TEXT_ALPHA,
TEXT_COLOR, ICON_TINT, CURRENT_VISIBLE_HEIGHT};
} }
...@@ -66,6 +66,10 @@ class StatusIndicatorViewBinder { ...@@ -66,6 +66,10 @@ class StatusIndicatorViewBinder {
final ColorStateList tint = final ColorStateList tint =
ColorStateList.valueOf(model.get(StatusIndicatorProperties.ICON_TINT)); ColorStateList.valueOf(model.get(StatusIndicatorProperties.ICON_TINT));
text.setDrawableTintColor(tint); text.setDrawableTintColor(tint);
} else if (StatusIndicatorProperties.CURRENT_VISIBLE_HEIGHT == propertyKey) {
final float yOffset = model.get(StatusIndicatorProperties.CURRENT_VISIBLE_HEIGHT)
- view.javaViewRoot.getHeight();
view.javaViewRoot.setTranslationY(yOffset);
} else { } else {
assert false : "Unhandled property detected in StatusIndicatorViewBinder!"; assert false : "Unhandled property detected in StatusIndicatorViewBinder!";
} }
......
...@@ -526,29 +526,6 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve ...@@ -526,29 +526,6 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve
@Override @Override
public void onControlsOffsetChanged(int topOffset, int topControlsMinHeightOffset, public void onControlsOffsetChanged(int topOffset, int topControlsMinHeightOffset,
int bottomOffset, int bottomControlsMinHeightOffset, boolean needsAnimate) { int bottomOffset, int bottomControlsMinHeightOffset, boolean needsAnimate) {
// If the browser controls can't be animated, we shouldn't listen for the offset
// changes.
if (mCanAnimateNativeBrowserControls == null
|| !mCanAnimateNativeBrowserControls.get()) {
return;
}
// Controls need to be offset to match the composited layer, which is
// anchored at the bottom of the controls container.
setControlContainerTopMargin(getToolbarExtraYOffset());
}
@Override
public void onTopControlsHeightChanged(
int topControlsHeight, int topControlsMinHeight) {
// If the browser controls can be animated, we shouldn't set the extra offset here.
// Instead, that should happen when the animation starts (i.e. we get new offsets)
// to prevent the Android view from jumping before the animation starts.
if (mCanAnimateNativeBrowserControls == null
|| mCanAnimateNativeBrowserControls.get()) {
return;
}
// Controls need to be offset to match the composited layer, which is // Controls need to be offset to match the composited layer, which is
// anchored at the bottom of the controls container. // anchored at the bottom of the controls container.
setControlContainerTopMargin(getToolbarExtraYOffset()); setControlContainerTopMargin(getToolbarExtraYOffset());
......
...@@ -4,12 +4,21 @@ ...@@ -4,12 +4,21 @@
package org.chromium.chrome.browser.fullscreen; package org.chromium.chrome.browser.fullscreen;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
...@@ -120,6 +129,151 @@ public class FullscreenManagerUnitTest { ...@@ -120,6 +129,151 @@ public class FullscreenManagerUnitTest {
.onTopControlsHeightChanged(topControlsHeight, topControlsMinHeight); .onTopControlsHeightChanged(topControlsHeight, topControlsMinHeight);
} }
@Test
public void testBrowserDrivenHeightIncreaseAnimation() {
final int topControlsHeight = TOOLBAR_HEIGHT + EXTRA_TOP_CONTROL_HEIGHT;
final int topControlsMinHeight = EXTRA_TOP_CONTROL_HEIGHT;
// Simulate that we can't animate native browser controls.
when(mFullscreenManager.getTab()).thenReturn(null);
mFullscreenManager.setAnimateBrowserControlsHeightChanges(true);
mFullscreenManager.setTopControlsHeight(topControlsHeight, topControlsMinHeight);
assertNotEquals("Min-height offset shouldn't immediately change.", topControlsMinHeight,
mFullscreenManager.getTopControlsMinHeightOffset());
assertNotNull("Animator should be initialized.",
mFullscreenManager.getControlsAnimatorForTesting());
for (long time = 50; time < mFullscreenManager.getControlsAnimationDurationMsForTesting();
time += 50) {
int previousMinHeightOffset = mFullscreenManager.getTopControlsMinHeightOffset();
int previousContentOffset = mFullscreenManager.getContentOffset();
mFullscreenManager.getControlsAnimatorForTesting().setCurrentPlayTime(time);
assertThat(mFullscreenManager.getTopControlsMinHeightOffset(),
greaterThan(previousMinHeightOffset));
assertThat(mFullscreenManager.getContentOffset(), greaterThan(previousContentOffset));
}
mFullscreenManager.getControlsAnimatorForTesting().end();
assertEquals("Min-height offset should be equal to min-height after animation.",
mFullscreenManager.getTopControlsMinHeightOffset(), topControlsMinHeight);
assertEquals("Content offset should be equal to controls height after animation.",
mFullscreenManager.getContentOffset(), topControlsHeight);
assertNull(mFullscreenManager.getControlsAnimatorForTesting());
}
@Test
public void testBrowserDrivenHeightDecreaseAnimation() {
// Simulate that we can't animate native browser controls.
when(mFullscreenManager.getTab()).thenReturn(null);
mFullscreenManager.setTopControlsHeight(
TOOLBAR_HEIGHT + EXTRA_TOP_CONTROL_HEIGHT, EXTRA_TOP_CONTROL_HEIGHT);
mFullscreenManager.setAnimateBrowserControlsHeightChanges(true);
mFullscreenManager.setTopControlsHeight(TOOLBAR_HEIGHT, 0);
assertNotEquals("Min-height offset shouldn't immediately change.", 0,
mFullscreenManager.getTopControlsMinHeightOffset());
assertNotNull("Animator should be initialized.",
mFullscreenManager.getControlsAnimatorForTesting());
for (long time = 50; time < mFullscreenManager.getControlsAnimationDurationMsForTesting();
time += 50) {
int previousMinHeightOffset = mFullscreenManager.getTopControlsMinHeightOffset();
int previousContentOffset = mFullscreenManager.getContentOffset();
mFullscreenManager.getControlsAnimatorForTesting().setCurrentPlayTime(time);
assertThat(mFullscreenManager.getTopControlsMinHeightOffset(),
lessThan(previousMinHeightOffset));
assertThat(mFullscreenManager.getContentOffset(), lessThan(previousContentOffset));
}
mFullscreenManager.getControlsAnimatorForTesting().end();
assertEquals("Min-height offset should be equal to the min-height after animation.",
mFullscreenManager.getTopControlsMinHeight(),
mFullscreenManager.getTopControlsMinHeightOffset());
assertEquals("Content offset should be equal to controls height after animation.",
mFullscreenManager.getTopControlsHeight(), mFullscreenManager.getContentOffset());
assertNull(mFullscreenManager.getControlsAnimatorForTesting());
}
@Test
public void testChangeTopHeightWithoutAnimation_Browser() {
// Simulate that we can't animate native browser controls.
when(mFullscreenManager.getTab()).thenReturn(null);
// Increase the height.
mFullscreenManager.setTopControlsHeight(
TOOLBAR_HEIGHT + EXTRA_TOP_CONTROL_HEIGHT, EXTRA_TOP_CONTROL_HEIGHT);
verify(mFullscreenManager).showAndroidControls(false);
assertEquals("Controls should be fully shown after changing the height.",
TOOLBAR_HEIGHT + EXTRA_TOP_CONTROL_HEIGHT, mFullscreenManager.getContentOffset());
assertEquals("Controls should be fully shown after changing the height.", 0,
mFullscreenManager.getTopControlOffset());
assertEquals("Min-height offset should be equal to the min-height after height changes.",
EXTRA_TOP_CONTROL_HEIGHT, mFullscreenManager.getTopControlsMinHeightOffset());
// Decrease the height.
mFullscreenManager.setTopControlsHeight(TOOLBAR_HEIGHT, 0);
// Controls should be fully shown after changing the height.
verify(mFullscreenManager, times(2)).showAndroidControls(false);
assertEquals("Controls should be fully shown after changing the height.", TOOLBAR_HEIGHT,
mFullscreenManager.getContentOffset());
assertEquals("Controls should be fully shown after changing the height.", 0,
mFullscreenManager.getTopControlOffset());
assertEquals("Min-height offset should be equal to the min-height after height changes.", 0,
mFullscreenManager.getTopControlsMinHeightOffset());
}
@Test
public void testChangeTopHeightWithoutAnimation_Native() {
int contentOffset = mFullscreenManager.getContentOffset();
int controlOffset = mFullscreenManager.getTopControlOffset();
int minHeightOffset = mFullscreenManager.getTopControlsMinHeightOffset();
// Increase the height.
mFullscreenManager.setTopControlsHeight(
TOOLBAR_HEIGHT + EXTRA_TOP_CONTROL_HEIGHT, EXTRA_TOP_CONTROL_HEIGHT);
// Controls visibility and offsets should be managed by native.
verify(mFullscreenManager, never()).showAndroidControls(anyBoolean());
assertEquals("Content offset should have the initial value before round-trip to native.",
contentOffset, mFullscreenManager.getContentOffset());
assertEquals("Controls offset should have the initial value before round-trip to native.",
controlOffset, mFullscreenManager.getTopControlOffset());
assertEquals("Min-height offset should have the initial value before round-trip to native.",
minHeightOffset, mFullscreenManager.getTopControlsMinHeightOffset());
verify(mBrowserControlsStateProviderObserver)
.onTopControlsHeightChanged(
TOOLBAR_HEIGHT + EXTRA_TOP_CONTROL_HEIGHT, EXTRA_TOP_CONTROL_HEIGHT);
contentOffset = TOOLBAR_HEIGHT + EXTRA_TOP_CONTROL_HEIGHT;
controlOffset = 0;
minHeightOffset = EXTRA_TOP_CONTROL_HEIGHT;
// Simulate the offset coming from cc::BrowserControlsOffsetManager.
mFullscreenManager.getTabControlsObserverForTesting().onBrowserControlsOffsetChanged(
mTab, controlOffset, 0, contentOffset, minHeightOffset, 0);
// Decrease the height.
mFullscreenManager.setTopControlsHeight(TOOLBAR_HEIGHT, 0);
// Controls visibility and offsets should be managed by native.
verify(mFullscreenManager, never()).showAndroidControls(anyBoolean());
assertEquals("Controls should be fully shown after getting the offsets from native.",
contentOffset, mFullscreenManager.getContentOffset());
assertEquals("Controls should be fully shown after getting the offsets from native.",
controlOffset, mFullscreenManager.getTopControlOffset());
assertEquals("Min-height offset should be equal to the min-height"
+ " after getting the offsets from native.",
minHeightOffset, mFullscreenManager.getTopControlsMinHeightOffset());
verify(mBrowserControlsStateProviderObserver).onTopControlsHeightChanged(TOOLBAR_HEIGHT, 0);
}
// controlsResizeView tests --- // controlsResizeView tests ---
// For these tests, we will simulate the scrolls assuming we either completely show or hide (or // For these tests, we will simulate the scrolls assuming we either completely show or hide (or
// scroll until the min-height) the controls and don't leave at in-between positions. The reason // scroll until the min-height) the controls and don't leave at in-between positions. The reason
......
...@@ -153,22 +153,25 @@ public class StatusIndicatorMediatorTest { ...@@ -153,22 +153,25 @@ public class StatusIndicatorMediatorTest {
} }
@Test @Test
public void testSkipAnimationIfCannotAnimateNativeBrowserControls() { public void testHeightChangeToZeroKeepsAndroidViewVisibleIfCannotAnimateNativeControls() {
// Assume we can't animate the native browser controls. // Assume we can't animate native controls.
when(mCanAnimateNativeBrowserControls.get()).thenReturn(false); when(mCanAnimateNativeBrowserControls.get()).thenReturn(false);
// Show the status indicator.
// Show the indicator. setViewHeight(70);
setViewHeight(50);
mMediator.onLayoutChange(mStatusIndicatorView, 0, 0, 0, 0, 0, 0, 0, 0); mMediator.onLayoutChange(mStatusIndicatorView, 0, 0, 0, 0, 0, 0, 0, 0);
// The indicator should be visible immediately. mMediator.onControlsOffsetChanged(0, 70, 0, 0, false);
// The Android view should be visible at this point.
assertEquals(View.VISIBLE, mModel.get(StatusIndicatorProperties.ANDROID_VIEW_VISIBILITY)); assertEquals(View.VISIBLE, mModel.get(StatusIndicatorProperties.ANDROID_VIEW_VISIBILITY));
assertTrue(mModel.get(StatusIndicatorProperties.COMPOSITED_VIEW_VISIBLE)); // Now hide it.
// Hide the indicator.
mMediator.updateVisibilityForTesting(true); mMediator.updateVisibilityForTesting(true);
// The indicator should hide immediately. // The hiding animation...
mMediator.onControlsOffsetChanged(0, 30, 0, 0, false);
// Android view will be VISIBLE during the animation.
assertEquals(View.VISIBLE, mModel.get(StatusIndicatorProperties.ANDROID_VIEW_VISIBILITY));
mMediator.onControlsOffsetChanged(0, 0, 0, 0, false);
// The view will be GONE once the animation ends and the indicator is completely out of
// screen bounds.
assertEquals(View.GONE, mModel.get(StatusIndicatorProperties.ANDROID_VIEW_VISIBILITY)); assertEquals(View.GONE, mModel.get(StatusIndicatorProperties.ANDROID_VIEW_VISIBILITY));
assertFalse(mModel.get(StatusIndicatorProperties.COMPOSITED_VIEW_VISIBLE));
} }
private void setViewHeight(int height) { private void setViewHeight(int height) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment