Create dynamic resource for GTS RecyclerView
The GridTabSwitcher RecyclerView would be rendered to a Bitmap
as the background in TabListSceneLayer, so that the shrinking Tab
can be animated on top of the (Bitmap version of) GTS RecyclerView.
Bug: 964406
Change-Id: I9962cbcce42ad7787e170a2fd855375a318cf324
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1617892
Commit-Queue: Wei-Yin Chen (陳威尹) <wychen@chromium.org>
Reviewed-by: Yusuf Ozuysal <yusufo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#662498}
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcher.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcher.java
index c50daee..96ba5bd 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcher.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcher.java
@@ -24,4 +24,9 @@
interface GridVisibilityObserver extends OverviewModeBehavior.OverviewModeObserver {}
GridController getGridController();
+
+ /**
+ * @return The dynamic resource ID of the GridTabSwitcher RecyclerView.
+ */
+ int getResourceId();
}
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherCoordinator.java
index 8bc9790..589b39ad 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherCoordinator.java
@@ -81,7 +81,7 @@
mTabGridCoordinator = new TabListCoordinator(TabListCoordinator.TabListMode.GRID, context,
tabModelSelector, mMultiThumbnailCardProvider, titleProvider, true,
mMediator::getCreateGroupButtonOnClickListener, gridCardOnClickListenerProvider,
- compositorViewHolder, true,
+ compositorViewHolder, compositorViewHolder.getDynamicResourceLoader(), true,
org.chromium.chrome.tab_ui.R.layout.grid_tab_switcher_layout, COMPONENT_NAME);
HistoryNavigationLayout navigation =
compositorViewHolder.findViewById(R.id.history_navigation);
@@ -103,6 +103,11 @@
return mMediator;
}
+ @Override
+ public int getResourceId() {
+ return mTabGridCoordinator.getResourceId();
+ }
+
/**
* Reset the tab grid with the given {@link TabModel}. Can be null.
* @param tabList The current {@link TabList} to show the tabs for in the grid.
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
index cf0751e..ab644b2 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
@@ -41,7 +41,7 @@
mTabListCoordinator = new TabListCoordinator(TabListCoordinator.TabListMode.GRID, context,
tabModelSelector, tabContentManager::getTabThumbnailWithCallback, null, false, null,
- null, compositorViewHolder, false, R.layout.tab_list_recycler_view_layout,
+ null, compositorViewHolder, null, false, R.layout.tab_list_recycler_view_layout,
COMPONENT_NAME);
mMediator = new TabGridDialogMediator(context, this::resetWithListOfTabs,
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridSheetCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridSheetCoordinator.java
index e9ebf9e..219050e 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridSheetCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridSheetCoordinator.java
@@ -45,7 +45,7 @@
mTabGridCoordinator = new TabListCoordinator(TabListCoordinator.TabListMode.GRID, context,
tabModelSelector, tabContentManager::getTabThumbnailWithCallback, null, false, null,
- null, bottomSheetController.getBottomSheet(), false,
+ null, bottomSheetController.getBottomSheet(), null, false,
R.layout.tab_list_recycler_view_layout, COMPONENT_NAME);
mMediator = new TabGridSheetMediator(mContext, bottomSheetController,
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
index 04371c49..2ab80e857 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
@@ -76,7 +76,7 @@
mTabStripCoordinator = new TabListCoordinator(TabListCoordinator.TabListMode.STRIP,
mContext, tabModelSelector, null, null, false, null, null,
- mTabStripToolbarCoordinator.getTabListContainerView(), true,
+ mTabStripToolbarCoordinator.getTabListContainerView(), null, true,
R.layout.tab_list_recycler_view_layout, COMPONENT_NAME);
mTabGridSheetCoordinator =
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
index 892ea19..2781f53b 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
@@ -27,6 +27,7 @@
import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.RecyclerViewAdapter;
import org.chromium.ui.modelutil.SimpleRecyclerViewMcpBase;
+import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -63,6 +64,8 @@
* @param createGroupButtonProvider {@link TabListMediator.CreateGroupButtonProvider}
* to provide "Create group" button.
* @param parentView {@link ViewGroup} The root view of the UI.
+ * @param dynamicResourceLoader The {@link DynamicResourceLoader} to register dynamic UI
+ * resource for compositor layer animation.
* @param attachToParent Whether the UI should attach to root view.
* @param layoutId ID of the layout resource.
* @param componentName A unique string uses to identify different components for UMA recording.
@@ -70,13 +73,13 @@
* through actions.xml file.
*/
TabListCoordinator(@TabListMode int mode, Context context, TabModelSelector tabModelSelector,
- TabListMediator.ThumbnailProvider thumbnailProvider,
- TabListMediator.TitleProvider titleProvider, boolean closeRelatedTabs,
+ @Nullable TabListMediator.ThumbnailProvider thumbnailProvider,
+ @Nullable TabListMediator.TitleProvider titleProvider, boolean closeRelatedTabs,
@Nullable TabListMediator.CreateGroupButtonProvider createGroupButtonProvider,
@Nullable TabListMediator
.GridCardOnClickListenerProvider gridCardOnClickListenerProvider,
- @NonNull ViewGroup parentView, boolean attachToParent, @LayoutRes int layoutId,
- String componentName) {
+ @NonNull ViewGroup parentView, @Nullable DynamicResourceLoader dynamicResourceLoader,
+ boolean attachToParent, @LayoutRes int layoutId, String componentName) {
TabListModel tabListModel = new TabListModel();
mMode = mode;
@@ -125,6 +128,10 @@
mRecyclerView.setHasFixedSize(true);
+ if (dynamicResourceLoader != null) {
+ mRecyclerView.createDynamicView(dynamicResourceLoader);
+ }
+
TabListFaviconProvider tabListFaviconProvider =
new TabListFaviconProvider(context, Profile.getLastUsedProfile());
@@ -169,4 +176,8 @@
public void destroy() {
mMediator.destroy();
}
+
+ int getResourceId() {
+ return mRecyclerView.getResourceId();
+ }
}
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java
index a345f987..aead8b6 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java
@@ -8,18 +8,24 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
+import android.annotation.SuppressLint;
import android.content.Context;
+import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;
+import android.view.ViewParent;
import org.chromium.ui.interpolators.BakedBezierInterpolator;
+import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
+import org.chromium.ui.resources.dynamics.ViewResourceAdapter;
/**
* A custom RecyclerView implementation for the tab grid, to handle show/hide logic in class.
*/
class TabListRecyclerView extends RecyclerView {
public static final long BASE_ANIMATION_DURATION_MS = 218;
+ private ViewResourceAdapter mDynamicView;
/**
* An interface to listen to visibility related changes on this {@link RecyclerView}.
@@ -84,12 +90,49 @@
@Override
public void onAnimationEnd(Animator animation) {
mListener.finishedShowing();
+
+ if (mDynamicView != null)
+ mDynamicView.dropCachedBitmap();
}
});
if (!animate) mFadeInAnimator.end();
}
/**
+ * @return The ID for registering and using the dynamic resource in compositor.
+ */
+ int getResourceId() {
+ return getId();
+ }
+
+ /**
+ * Create a DynamicResource for this RecyclerView.
+ * The view resource can be obtained by {@link #getResourceId} in compositor layer.
+ */
+ void createDynamicView(DynamicResourceLoader loader) {
+ mDynamicView = new ViewResourceAdapter(this);
+ loader.registerResource(getResourceId(), mDynamicView);
+ }
+
+ @SuppressLint("NewApi") // Used on O+, invalidateChildInParent used for previous versions.
+ @Override
+ public void onDescendantInvalidated(View child, View target) {
+ super.onDescendantInvalidated(child, target);
+ if (mDynamicView != null) {
+ mDynamicView.invalidate(null);
+ }
+ }
+
+ @Override
+ public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
+ ViewParent retVal = super.invalidateChildInParent(location, dirty);
+ if (mDynamicView != null) {
+ mDynamicView.invalidate(dirty);
+ }
+ return retVal;
+ }
+
+ /**
* Start hiding the tab list.
* @param animate Whether the visibility change should be animated.
*/