Commit 9489bbc9 authored by Wei-Yin Chen (陳威尹)'s avatar Wei-Yin Chen (陳威尹) Committed by Commit Bot

Implement the Grid-to-Tab transition animation

Add a bare-bone implementation of the Grid-to-Tab expanding animation.
This is only used for the Grid Tab Switcher, and is behind a flag,
"TabToGTSAnimation".

Further optimization is needed.

Bug: 964406
Change-Id: Ie07275ac0ef622d52fd0bdf91fd389f3397f3b6f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1629046
Commit-Queue: Wei-Yin Chen (陳威尹) <wychen@chromium.org>
Reviewed-by: default avatarYusuf Ozuysal <yusufo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664629}
parent 71e32271
......@@ -48,9 +48,18 @@ public interface GridTabSwitcher {
void prepareOverview();
/**
* This is called after the compositor animation is done, for potential clean-up work.
* {@link OverviewModeBehavior.OverviewModeObserver#onOverviewModeFinishedHiding} happens after
* the Android View animation, but before the compositor animation.
*/
void postHiding();
/**
* @param forceUpdate Whether to measure the current location again. If not, return the last
* location measured on last layout, which can be wrong after scrolling.
* @return The {@link Rect} of the thumbnail of the current tab, relative to the
* GridTabSwitcher {@link TabListRecyclerView} coordinates.
*/
@NonNull
Rect getThumbnailLocationOfCurrentTab();
Rect getThumbnailLocationOfCurrentTab(boolean forceUpdate);
}
......@@ -111,9 +111,15 @@ public class GridTabSwitcherCoordinator
mMediator.prepareOverview();
}
@Override
public void postHiding() {
mMediator.postHiding();
}
@Override
@NonNull
public Rect getThumbnailLocationOfCurrentTab() {
public Rect getThumbnailLocationOfCurrentTab(boolean forceUpdate) {
if (forceUpdate) mTabGridCoordinator.updateThumbnailLocation();
return mTabGridCoordinator.getThumbnailLocationOfCurrentTab();
}
......
......@@ -19,6 +19,7 @@ import org.chromium.base.ContextUtils;
import org.chromium.base.ObserverList;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.UrlConstants;
import org.chromium.chrome.browser.compositor.CompositorViewHolder;
import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
......@@ -145,7 +146,8 @@ class GridTabSwitcherMediator
if (modelFilter instanceof TabGroupModelFilter) {
((TabGroupModelFilter) modelFilter).recordSessionsCount(tab);
}
setVisibility(false);
hideOverview(
!ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_TO_GTS_ANIMATION));
}
}
};
......@@ -208,7 +210,7 @@ class GridTabSwitcherMediator
mContainerViewModel.set(ANIMATE_VISIBILITY_CHANGES, true);
}
public void prepareOverview() {
void prepareOverview() {
mResetHandler.resetWithTabList(
mTabModelSelector.getTabModelFilterProvider().getCurrentTabModelFilter());
int initialPosition = Math.max(
......@@ -250,14 +252,17 @@ class GridTabSwitcherMediator
@Override
public void finishedHiding() {
// TODO(crbug.com/964406): see if we can lazily release it.
mResetHandler.resetWithTabList(null);
mContainerViewModel.set(INITIAL_SCROLL_INDEX, 0);
for (OverviewModeObserver observer : mObservers) {
observer.onOverviewModeFinishedHiding();
}
}
void postHiding() {
// TODO(crbug.com/964406): see if we can lazily release it.
mResetHandler.resetWithTabList(null);
mContainerViewModel.set(INITIAL_SCROLL_INDEX, 0);
}
/**
* Destroy any members that needs clean up.
*/
......
......@@ -165,7 +165,7 @@ public class TabListCoordinator implements Destroyable {
return mThumbnailLocationOfCurrentTab;
}
private void updateThumbnailLocation() {
void updateThumbnailLocation() {
Rect rect = mRecyclerView.getRectOfCurrentThumbnail(
mTabModelSelector.getTabModelFilterProvider().getCurrentTabModelFilter().index());
if (rect == null) return;
......
......@@ -54,6 +54,8 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
import org.chromium.chrome.browser.tabmodel.TabSelectionType;
import org.chromium.chrome.browser.util.FeatureUtilities;
import org.chromium.chrome.test.util.browser.Features;
import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
import org.chromium.testing.local.LocalRobolectricTestRunner;
import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel;
......@@ -67,7 +69,8 @@ import java.util.List;
*/
@RunWith(LocalRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
@Features.DisableFeatures(ChromeFeatureList.TAB_SWITCHER_ON_RETURN)
@DisableFeatures(ChromeFeatureList.TAB_SWITCHER_ON_RETURN)
@EnableFeatures(ChromeFeatureList.TAB_TO_GTS_ANIMATION)
public class GridTabSwitcherMediatorUnitTest {
@Rule
public TestRule mProcessor = new Features.JUnitProcessor();
......@@ -284,7 +287,7 @@ public class GridTabSwitcherMediatorUnitTest {
@Test
public void resetsToNullAfterHidingFinishes() {
initAndAssertAllProperties();
mMediator.finishedHiding();
mMediator.postHiding();
verify(mResetHandler).resetWithTabList(eq(null));
assertThat(mModel.get(TabListContainerProperties.INITIAL_SCROLL_INDEX), equalTo(0));
}
......
......@@ -105,7 +105,7 @@ public class GridTabSwitcherLayout
return;
}
shrinkTab(mGridTabSwitcher::getThumbnailLocationOfCurrentTab);
shrinkTab(() -> mGridTabSwitcher.getThumbnailLocationOfCurrentTab(false));
}
@Override
......@@ -166,8 +166,12 @@ public class GridTabSwitcherLayout
@Override
public void onOverviewModeStartedHiding(boolean showToolbar, boolean delayAnimation) {
// TODO(crbug.com/964406): implement zoom-in animation.
startHiding(mTabModelSelector.getCurrentTabId(), false);
if (!ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_TO_GTS_ANIMATION)) {
mGridTabSwitcher.postHiding();
return;
}
expandTab(mGridTabSwitcher.getThumbnailLocationOfCurrentTab(true));
}
@Override
......@@ -230,6 +234,53 @@ public class GridTabSwitcherLayout
mTabToSwitcherAnimation.start();
}
/**
* Animate expanding a tab from a source {@link Rect} area.
* @param source The source {@link Rect} area.
*/
private void expandTab(Rect source) {
LayoutTab sourceLayoutTab = createLayoutTab(mTabModelSelector.getCurrentTabId(),
mTabModelSelector.isIncognitoSelected(), NO_CLOSE_BUTTON, NEED_TITLE);
mLayoutTabs = new LayoutTab[] {sourceLayoutTab};
forceAnimationToFinish();
CompositorAnimationHandler handler = getAnimationHandler();
Collection<Animator> animationList = new ArrayList<>(5);
// Zoom in the source tab
animationList.add(CompositorAnimator.ofFloatProperty(handler, sourceLayoutTab,
LayoutTab.SCALE, source.width() / (getWidth() * mDpToPx), 1, ZOOMING_DURATION));
animationList.add(CompositorAnimator.ofFloatProperty(handler, sourceLayoutTab, LayoutTab.X,
source.left / mDpToPx, 0f, ZOOMING_DURATION));
animationList.add(CompositorAnimator.ofFloatProperty(
handler, sourceLayoutTab, LayoutTab.Y, source.top / mDpToPx, 0f, ZOOMING_DURATION));
animationList.add(CompositorAnimator.ofFloatProperty(
handler, sourceLayoutTab, LayoutTab.DECORATION_ALPHA, 0f, 1f, ZOOMING_DURATION));
// TODO(crbug.com/964406): when shrinking to the bottom row, bottom of the tab goes up and
// down, making the "create group" visible for a while.
animationList.add(CompositorAnimator.ofFloatProperty(handler, sourceLayoutTab,
LayoutTab.MAX_CONTENT_HEIGHT, getWidth(),
sourceLayoutTab.getUnclampedOriginalContentHeight(), ZOOMING_DURATION,
BakedBezierInterpolator.FADE_IN_CURVE));
mTabToSwitcherAnimation = new AnimatorSet();
mTabToSwitcherAnimation.playTogether(animationList);
mTabToSwitcherAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mTabToSwitcherAnimation = null;
mGridTabSwitcher.postHiding();
reportAnimationPerf();
}
});
mStartFrame = mFrameCount;
mStartTime = SystemClock.elapsedRealtime();
mTabToSwitcherAnimation.start();
}
void setPerfListenerForTesting(PerfListener perfListener) {
mPerfListenerForTesting = perfListener;
}
......
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