Commit 6b362711 authored by Mia Glaese's avatar Mia Glaese Committed by Commit Bot

[Start Surface] Refactor Task Surface Scrolling Behavior using AppBarLayout

CL has no user visible changes.

Restructuring TasksSurface with AppBarLayout.
Adapting StartSurface and sub components to work with new layout.

Before: RecyclerView inside NestedScrollView did not recycle views.
Now: RecyclerView recycles views inside CoordinatorLayout.

Bug: 1000295

Change-Id: I73b01f1f4efcb7e263894b64e2b0f81a07229f23
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1865399
Commit-Queue: Mia Glaese <glamia@chromium.org>
Reviewed-by: default avatarYusuf Ozuysal <yusufo@chromium.org>
Reviewed-by: default avatarGanggui Tang <gogerald@chromium.org>
Cr-Commit-Position: refs/heads/master@{#707970}
parent e8cbe5c3
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2019 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:background="@color/modern_primary_color"
android:visibility="gone" />
...@@ -5,13 +5,10 @@ ...@@ -5,13 +5,10 @@
package org.chromium.chrome.features.start_surface; package org.chromium.chrome.features.start_surface;
import android.app.Activity; import android.app.Activity;
import android.support.v4.widget.NestedScrollView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.Nullable;
import com.google.android.libraries.feed.api.client.stream.Stream; import com.google.android.libraries.feed.api.client.stream.Stream;
import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeActivity;
...@@ -47,18 +44,12 @@ class ExploreSurfaceCoordinator implements FeedSurfaceCoordinator.FeedSurfaceDel ...@@ -47,18 +44,12 @@ class ExploreSurfaceCoordinator implements FeedSurfaceCoordinator.FeedSurfaceDel
} }
ExploreSurfaceCoordinator(ChromeActivity activity, ViewGroup parentView, ExploreSurfaceCoordinator(ChromeActivity activity, ViewGroup parentView,
@Nullable ViewGroup headerContainerView, PropertyModel containerPropertyModel) { PropertyModel containerPropertyModel, boolean hasHeader) {
mActivity = activity; mActivity = activity;
mHasHeader = (headerContainerView != null); mHasHeader = hasHeader;
mPropertyModelChangeProcessor = PropertyModelChangeProcessor.create(containerPropertyModel, mPropertyModelChangeProcessor = PropertyModelChangeProcessor.create(
new ExploreSurfaceViewBinder.ViewHolder(parentView, containerPropertyModel, parentView, ExploreSurfaceViewBinder::bind);
!mHasHeader
? null
: (NestedScrollView) LayoutInflater.from(activity).inflate(
R.layout.ss_explore_scroll_container, parentView, false),
headerContainerView),
ExploreSurfaceViewBinder::bind);
mFeedSurfaceCreator = new FeedSurfaceCreator() { mFeedSurfaceCreator = new FeedSurfaceCreator() {
@Override @Override
public FeedSurfaceCoordinator createFeedSurfaceCoordinator(boolean isInNightMode) { public FeedSurfaceCoordinator createFeedSurfaceCoordinator(boolean isInNightMode) {
......
...@@ -6,17 +6,14 @@ package org.chromium.chrome.features.start_surface; ...@@ -6,17 +6,14 @@ package org.chromium.chrome.features.start_surface;
import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.BOTTOM_BAR_HEIGHT; import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.BOTTOM_BAR_HEIGHT;
import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.FEED_SURFACE_COORDINATOR; import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.FEED_SURFACE_COORDINATOR;
import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.IS_BOTTOM_BAR_VISIBLE;
import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.IS_EXPLORE_SURFACE_VISIBLE; import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.IS_EXPLORE_SURFACE_VISIBLE;
import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.IS_SHOWING_OVERVIEW; import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.IS_SHOWING_OVERVIEW;
import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.TOP_BAR_HEIGHT; import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.TOP_BAR_HEIGHT;
import android.support.v4.widget.NestedScrollView;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;
import androidx.annotation.Nullable;
import org.chromium.ui.UiUtils; import org.chromium.ui.UiUtils;
import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyKey;
...@@ -24,76 +21,39 @@ import org.chromium.ui.modelutil.PropertyModel; ...@@ -24,76 +21,39 @@ import org.chromium.ui.modelutil.PropertyModel;
/** Binder for the explore surface. */ /** Binder for the explore surface. */
class ExploreSurfaceViewBinder { class ExploreSurfaceViewBinder {
/** public static void bind(PropertyModel model, ViewGroup parentView, PropertyKey propertyKey) {
* The view holder holds the parent view, the possible scroll container and header container
* view.
*/
public static class ViewHolder {
public final ViewGroup parentView;
@Nullable
public final NestedScrollView scrollContainer;
@Nullable
public final ViewGroup headerContainerView;
ViewHolder(ViewGroup parentView, @Nullable NestedScrollView scrollContainer,
@Nullable ViewGroup headerContainerView) {
assert (scrollContainer == null) == (headerContainerView == null);
this.parentView = parentView;
this.scrollContainer = scrollContainer;
this.headerContainerView = headerContainerView;
}
}
public static void bind(PropertyModel model, ViewHolder view, PropertyKey propertyKey) {
if (propertyKey == IS_EXPLORE_SURFACE_VISIBLE) { if (propertyKey == IS_EXPLORE_SURFACE_VISIBLE) {
setVisibility(view, model, setVisibility(parentView, model,
model.get(IS_EXPLORE_SURFACE_VISIBLE) && model.get(IS_SHOWING_OVERVIEW)); model.get(IS_EXPLORE_SURFACE_VISIBLE) && model.get(IS_SHOWING_OVERVIEW));
} else if (propertyKey == IS_SHOWING_OVERVIEW) { } else if (propertyKey == IS_SHOWING_OVERVIEW) {
setVisibility(view, model, setVisibility(parentView, model,
model.get(IS_EXPLORE_SURFACE_VISIBLE) && model.get(IS_SHOWING_OVERVIEW)); model.get(IS_EXPLORE_SURFACE_VISIBLE) && model.get(IS_SHOWING_OVERVIEW));
} }
} }
/** /**
* Set the explore surface visibility. * Set the explore surface visibility.
* Note that if the {@link ViewHolder.headerContainerView} is not null, the feed surface view is * @param parentView The parent view of the feed.
* added to the {@link ViewHolder.headerContainerView}. This is for the alignment between the
* {@link ViewHolder.headerContainerView} and the feed surface view to avoid another level of
* view hiearachy. Then {@link ViewHolder.headerContainerView} is added to {@link
* ViewHolder.scrollContainer}. This allows the {@link ViewHolder.headerContainerView} scrolls
* together with the feed surface view. Finally, we add the {@link ViewHolder.scrollContainer}
* to the {@link ViewHolder.parentView}. If the {@link ViewHolder.headerContainerView} is null,
* then the feed surface view is added to the {@link ViewHolder.parentView} directly.
* @param viewHolder The view holder holds the parent and possible the header container view.
* @param model The property model. * @param model The property model.
* @param isShowing Whether set the surface to visible or not. * @param isShowing Whether set the surface to visible or not.
*/ */
// TODO(crbug.com/982018): Attach feed directly to TasksSurfaceContainerView
// and get rid of tasks_surface_body to improve performance.
private static void setVisibility( private static void setVisibility(
ViewHolder viewHolder, PropertyModel model, boolean isShowing) { ViewGroup parentView, PropertyModel model, boolean isShowing) {
if (model.get(FEED_SURFACE_COORDINATOR) == null) return; if (model.get(FEED_SURFACE_COORDINATOR) == null) return;
if (viewHolder.headerContainerView != null) {
if (viewHolder.scrollContainer.getParent() == null) {
viewHolder.scrollContainer.addView(viewHolder.headerContainerView);
FrameLayout.LayoutParams layoutParams =
(FrameLayout.LayoutParams) viewHolder.scrollContainer.getLayoutParams();
layoutParams.bottomMargin = model.get(BOTTOM_BAR_HEIGHT);
layoutParams.topMargin = model.get(TOP_BAR_HEIGHT);
viewHolder.parentView.addView(viewHolder.scrollContainer);
}
viewHolder.scrollContainer.setVisibility(isShowing ? View.VISIBLE : View.GONE);
}
View feedSurfaceView = model.get(FEED_SURFACE_COORDINATOR).getView(); View feedSurfaceView = model.get(FEED_SURFACE_COORDINATOR).getView();
if (isShowing) { if (isShowing) {
if (viewHolder.headerContainerView == null) { parentView.addView(feedSurfaceView);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams( // We only need to make room for the top and bottom bar if in the TWOPANE surface {@link
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); // SurfaceMode.TWO_PANES}. The bottom bar is only visible in the TWOPANE surface {@link
// SurfaceMode.TWO_PANES}.
if (model.get(IS_BOTTOM_BAR_VISIBLE)) {
FrameLayout.LayoutParams layoutParams =
(FrameLayout.LayoutParams) feedSurfaceView.getLayoutParams();
layoutParams.bottomMargin = model.get(BOTTOM_BAR_HEIGHT); layoutParams.bottomMargin = model.get(BOTTOM_BAR_HEIGHT);
layoutParams.topMargin = model.get(TOP_BAR_HEIGHT); layoutParams.topMargin = model.get(TOP_BAR_HEIGHT);
viewHolder.parentView.addView(feedSurfaceView, layoutParams);
} else {
viewHolder.headerContainerView.addView(feedSurfaceView);
} }
} else { } else {
UiUtils.removeViewFromParent(feedSurfaceView); UiUtils.removeViewFromParent(feedSurfaceView);
......
...@@ -30,13 +30,12 @@ class SecondaryTasksSurfaceViewBinder { ...@@ -30,13 +30,12 @@ class SecondaryTasksSurfaceViewBinder {
private static void setVisibility( private static void setVisibility(
TasksSurfaceViewBinder.ViewHolder viewHolder, PropertyModel model, boolean isShowing) { TasksSurfaceViewBinder.ViewHolder viewHolder, PropertyModel model, boolean isShowing) {
if (isShowing && viewHolder.tasksSurfaceView.getParent() == null) { if (isShowing && viewHolder.tasksSurfaceView.getParent() == null) {
viewHolder.parentView.addView(viewHolder.tasksSurfaceView);
MarginLayoutParams layoutParams = MarginLayoutParams layoutParams =
(MarginLayoutParams) viewHolder.scrollContainer.getLayoutParams(); (MarginLayoutParams) viewHolder.tasksSurfaceView.getLayoutParams();
layoutParams.topMargin = model.get(TOP_BAR_HEIGHT); layoutParams.topMargin = model.get(TOP_BAR_HEIGHT);
viewHolder.parentView.addView(viewHolder.scrollContainer);
viewHolder.scrollContainer.addView(viewHolder.tasksSurfaceView);
} }
viewHolder.scrollContainer.setVisibility(isShowing ? View.VISIBLE : View.GONE); viewHolder.tasksSurfaceView.setVisibility(isShowing ? View.VISIBLE : View.GONE);
} }
} }
...@@ -6,10 +6,6 @@ package org.chromium.chrome.features.start_surface; ...@@ -6,10 +6,6 @@ package org.chromium.chrome.features.start_surface;
import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.TOP_BAR_HEIGHT; import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.TOP_BAR_HEIGHT;
import android.support.v4.widget.NestedScrollView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeActivity;
...@@ -171,14 +167,11 @@ public class StartSurfaceCoordinator implements StartSurface { ...@@ -171,14 +167,11 @@ public class StartSurfaceCoordinator implements StartSurface {
mPropertyModel, mActivity.getToolbarManager().getFakeboxDelegate(), mPropertyModel, mActivity.getToolbarManager().getFakeboxDelegate(),
mSurfaceMode == SurfaceMode.SINGLE_PANE); mSurfaceMode == SurfaceMode.SINGLE_PANE);
// The tasks surface is added to the explore surface in the single pane mode below. mTasksSurfacePropertyModelChangeProcessor =
if (mSurfaceMode != SurfaceMode.SINGLE_PANE) { PropertyModelChangeProcessor.create(mPropertyModel,
// TODO(crbug.com/1000295): Make the tasks surface view scrollable together with the Tab new TasksSurfaceViewBinder.ViewHolder(
// switcher view in tasks only mode. mActivity.getCompositorViewHolder(), mTasksSurface.getView()),
mTasksSurfacePropertyModelChangeProcessor = TasksSurfaceViewBinder::bind);
createTasksViewPropertyModelChangeProcessor(mTasksSurface.getContainerView(),
TasksSurfaceViewBinder::bind, mSurfaceMode != SurfaceMode.TASKS_ONLY);
}
// There is nothing else to do for SurfaceMode.TASKS_ONLY. // There is nothing else to do for SurfaceMode.TASKS_ONLY.
if (mSurfaceMode == SurfaceMode.TASKS_ONLY) { if (mSurfaceMode == SurfaceMode.TASKS_ONLY) {
...@@ -190,12 +183,10 @@ public class StartSurfaceCoordinator implements StartSurface { ...@@ -190,12 +183,10 @@ public class StartSurfaceCoordinator implements StartSurface {
mActivity, mActivity.getCompositorViewHolder(), mPropertyModel); mActivity, mActivity.getCompositorViewHolder(), mPropertyModel);
} }
// TODO(crbug.com/1000295): Hide Tab switcher toolbar on explore pane in two panes mode,
// which should be done when adding fake search box.
mExploreSurfaceCoordinator = new ExploreSurfaceCoordinator(mActivity, mExploreSurfaceCoordinator = new ExploreSurfaceCoordinator(mActivity,
mActivity.getCompositorViewHolder(), mSurfaceMode == SurfaceMode.SINGLE_PANE ? mTasksSurface.getBodyViewContainer()
mSurfaceMode == SurfaceMode.SINGLE_PANE ? mTasksSurface.getContainerView() : null, : mActivity.getCompositorViewHolder(),
mPropertyModel); mPropertyModel, mSurfaceMode == SurfaceMode.SINGLE_PANE);
} }
private TabSwitcher.Controller initializeSecondaryTasksSurface() { private TabSwitcher.Controller initializeSecondaryTasksSurface() {
...@@ -208,33 +199,14 @@ public class StartSurfaceCoordinator implements StartSurface { ...@@ -208,33 +199,14 @@ public class StartSurfaceCoordinator implements StartSurface {
TabManagementModuleProvider.getDelegate().createTasksSurface(mActivity, TabManagementModuleProvider.getDelegate().createTasksSurface(mActivity,
propertyModel, mActivity.getToolbarManager().getFakeboxDelegate(), false); propertyModel, mActivity.getToolbarManager().getFakeboxDelegate(), false);
mSecondaryTasksSurfacePropertyModelChangeProcessor = mSecondaryTasksSurfacePropertyModelChangeProcessor =
createTasksViewPropertyModelChangeProcessor( PropertyModelChangeProcessor.create(mPropertyModel,
mSecondaryTasksSurface.getContainerView(), new TasksSurfaceViewBinder.ViewHolder(mActivity.getCompositorViewHolder(),
SecondaryTasksSurfaceViewBinder::bind, true); mSecondaryTasksSurface.getView()),
SecondaryTasksSurfaceViewBinder::bind);
if (mOnTabSelectingListener != null) { if (mOnTabSelectingListener != null) {
mSecondaryTasksSurface.setOnTabSelectingListener(mOnTabSelectingListener); mSecondaryTasksSurface.setOnTabSelectingListener(mOnTabSelectingListener);
mOnTabSelectingListener = null; mOnTabSelectingListener = null;
} }
return mSecondaryTasksSurface.getController(); return mSecondaryTasksSurface.getController();
} }
private PropertyModelChangeProcessor createTasksViewPropertyModelChangeProcessor(
ViewGroup container,
PropertyModelChangeProcessor.ViewBinder<PropertyModel,
TasksSurfaceViewBinder.ViewHolder, PropertyKey> binder,
boolean needScrollContainer) {
// TODO(crbug.com/1000295): Put TasksSurface view inside Tab switcher recycler view.
// This is a temporarily solution to make the TasksSurfaceView scroll together with the
// Tab switcher, however this solution has performance issue when the Tab switcher is in
// Grid mode, which is a launcher blocker. Check the bug details.
return PropertyModelChangeProcessor.create(mPropertyModel,
new TasksSurfaceViewBinder.ViewHolder(mActivity.getCompositorViewHolder(),
needScrollContainer
? (NestedScrollView) LayoutInflater.from(mActivity).inflate(
R.layout.ss_explore_scroll_container,
mActivity.getCompositorViewHolder(), false)
: null,
container),
binder);
}
} }
...@@ -8,31 +8,24 @@ import static org.chromium.chrome.features.start_surface.StartSurfaceProperties. ...@@ -8,31 +8,24 @@ import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.
import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.IS_SHOWING_OVERVIEW; import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.IS_SHOWING_OVERVIEW;
import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.TOP_BAR_HEIGHT; import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.TOP_BAR_HEIGHT;
import android.support.v4.widget.NestedScrollView;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams; import android.view.ViewGroup.MarginLayoutParams;
import androidx.annotation.Nullable;
import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModel;
/** The binder controls the display of the {@link TasksView} in its parent. */ /** The binder controls the display of the {@link TasksView} in its parent. */
class TasksSurfaceViewBinder { class TasksSurfaceViewBinder {
/** /**
* The view holder holds the parent view, the scroll container and the tasks surface view. * The view holder holds the parent view and the tasks surface view.
*/ */
public static class ViewHolder { public static class ViewHolder {
public final ViewGroup parentView; public final ViewGroup parentView;
@Nullable public final View tasksSurfaceView;
public final NestedScrollView scrollContainer;
public final ViewGroup tasksSurfaceView;
ViewHolder(ViewGroup parentView, @Nullable NestedScrollView scrollContainer, ViewHolder(ViewGroup parentView, View tasksSurfaceView) {
ViewGroup tasksSurfaceView) {
this.parentView = parentView; this.parentView = parentView;
this.scrollContainer = scrollContainer;
this.tasksSurfaceView = tasksSurfaceView; this.tasksSurfaceView = tasksSurfaceView;
} }
} }
...@@ -47,22 +40,20 @@ class TasksSurfaceViewBinder { ...@@ -47,22 +40,20 @@ class TasksSurfaceViewBinder {
private static void updateLayoutAndVisibility( private static void updateLayoutAndVisibility(
ViewHolder viewHolder, PropertyModel model, boolean isShowing) { ViewHolder viewHolder, PropertyModel model, boolean isShowing) {
ViewGroup targetView = viewHolder.scrollContainer == null ? viewHolder.tasksSurfaceView
: viewHolder.scrollContainer;
if (isShowing && viewHolder.tasksSurfaceView.getParent() == null) { if (isShowing && viewHolder.tasksSurfaceView.getParent() == null) {
viewHolder.parentView.addView(targetView); viewHolder.parentView.addView(viewHolder.tasksSurfaceView);
if (viewHolder.scrollContainer != null) targetView.addView(viewHolder.tasksSurfaceView); MarginLayoutParams layoutParams =
MarginLayoutParams layoutParams = (MarginLayoutParams) targetView.getLayoutParams(); (MarginLayoutParams) viewHolder.tasksSurfaceView.getLayoutParams();
layoutParams.bottomMargin = model.get(BOTTOM_BAR_HEIGHT); layoutParams.bottomMargin = model.get(BOTTOM_BAR_HEIGHT);
layoutParams.topMargin = model.get(TOP_BAR_HEIGHT); layoutParams.topMargin = model.get(TOP_BAR_HEIGHT);
} }
targetView.setVisibility(isShowing ? View.VISIBLE : View.GONE); viewHolder.tasksSurfaceView.setVisibility(isShowing ? View.VISIBLE : View.GONE);
} }
private static void setBottomBarHeight(ViewHolder viewHolder, int height) { private static void setBottomBarHeight(ViewHolder viewHolder, int height) {
ViewGroup targetView = viewHolder.scrollContainer == null ? viewHolder.tasksSurfaceView MarginLayoutParams layoutParams =
: viewHolder.scrollContainer; (MarginLayoutParams) viewHolder.tasksSurfaceView.getLayoutParams();
((MarginLayoutParams) targetView.getLayoutParams()).bottomMargin = height; if (layoutParams != null) layoutParams.bottomMargin = height;
} }
} }
...@@ -170,6 +170,7 @@ android_library("java") { ...@@ -170,6 +170,7 @@ android_library("java") {
"//third_party/android_deps:android_arch_lifecycle_viewmodel_java", "//third_party/android_deps:android_arch_lifecycle_viewmodel_java",
"//third_party/android_deps:android_support_v7_appcompat_java", "//third_party/android_deps:android_support_v7_appcompat_java",
"//third_party/android_deps:androidx_annotation_annotation_java", "//third_party/android_deps:androidx_annotation_annotation_java",
"//third_party/android_deps:com_android_support_design_java",
"//third_party/android_deps:com_android_support_recyclerview_v7_java", "//third_party/android_deps:com_android_support_recyclerview_v7_java",
"//third_party/android_deps:com_android_support_support_compat_java", "//third_party/android_deps:com_android_support_support_compat_java",
"//third_party/android_deps:com_android_support_support_v13_java", "//third_party/android_deps:com_android_support_support_v13_java",
......
...@@ -8,63 +8,76 @@ ...@@ -8,63 +8,76 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:orientation="vertical">
<!-- Search box --> <android.support.design.widget.AppBarLayout
<include layout="@layout/fake_search_box_layout"/> android:id="@+id/task_surface_header"
<HorizontalScrollView android:id="@+id/mv_tiles_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@color/modern_primary_color" app:elevation="0dp">
android:visibility="gone" <include layout="@layout/fake_search_box_layout"/>
android:scrollbars="none"> <HorizontalScrollView android:id="@+id/mv_tiles_container"
<LinearLayout android:id="@+id/mv_tiles_layout" android:layout_width="match_parent"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_height="match_parent" android:background="@color/modern_primary_color"
android:orientation="horizontal" android:visibility="gone"
android:paddingBottom="@dimen/tasks_view_items_vertical_spacing" /> android:scrollbars="none"
</HorizontalScrollView> app:layout_scrollFlags="scroll">
<LinearLayout android:id="@+id/mv_tiles_layout"
<LinearLayout android:layout_width="wrap_content"
android:id="@+id/tab_switcher_title" android:layout_height="match_parent"
android:layout_width="match_parent" android:orientation="horizontal"
android:layout_height="wrap_content" android:paddingBottom="@dimen/tasks_view_items_vertical_spacing" />
android:paddingStart="12dp" </HorizontalScrollView>
android:paddingEnd="4dp" <LinearLayout
android:paddingTop="8dp" android:id="@+id/tab_switcher_title"
android:paddingBottom="8dp" android:layout_width="match_parent"
android:visibility="gone"
android:background="@color/modern_primary_color"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1.0" android:paddingStart="12dp"
android:layout_gravity="center_vertical" android:paddingEnd="4dp"
android:gravity="center_vertical" android:paddingTop="8dp"
android:paddingStart="6dp" android:paddingBottom="8dp"
android:singleLine="true" android:visibility="gone"
android:textAppearance="@style/TextAppearance.BlackTitle2" android:background="@color/modern_primary_color"
android:text="@string/tab_switcher_carousel_title" /> android:orientation="horizontal"
<org.chromium.ui.widget.ChromeImageView app:layout_scrollFlags="scroll">
android:id="@+id/more_tabs" <TextView
android:layout_width="48dp" android:layout_width="0dp"
android:layout_height="48dp" android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end" android:layout_weight="1.0"
android:layout_marginTop="-16dp" android:layout_gravity="center_vertical"
android:layout_marginBottom="-16dp" android:gravity="center_vertical"
android:scaleType="center" android:paddingStart="6dp"
android:src="@drawable/ic_arrow_right" android:singleLine="true"
android:tint="@color/default_icon_color" android:textAppearance="@style/TextAppearance.BlackTitle2"
android:tintMode="src_in" android:text="@string/tab_switcher_carousel_title" />
android:paddingTop="16dp" <org.chromium.ui.widget.ChromeImageView
android:paddingBottom="16dp" android:id="@+id/more_tabs"
android:contentDescription="@string/accessibility_tab_switcher_carousel_more_tabs"/> android:layout_width="48dp"
</LinearLayout> android:layout_height="48dp"
android:layout_gravity="center_vertical|end"
android:layout_marginTop="-16dp"
android:layout_marginBottom="-16dp"
android:scaleType="center"
android:src="@drawable/ic_arrow_right"
android:tint="@color/default_icon_color"
android:tintMode="src_in"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:contentDescription="@string/accessibility_tab_switcher_carousel_more_tabs"/>
</LinearLayout>
<!-- TODO(crbug.com/982018): Make view stub to inflate only when needed. -->
<FrameLayout
android:id="@+id/carousel_tab_switcher_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/tab_carousel_start_margin"
android:visibility="gone"
app:layout_scrollFlags="scroll"/>
</android.support.design.widget.AppBarLayout>
<FrameLayout <FrameLayout
android:id="@+id/tab_switcher_container" android:id="@+id/tasks_surface_body"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</org.chromium.chrome.browser.tasks.TasksView> </org.chromium.chrome.browser.tasks.TasksView>
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.tasks; package org.chromium.chrome.browser.tasks;
import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import org.chromium.chrome.browser.compositor.layouts.Layout; import org.chromium.chrome.browser.compositor.layouts.Layout;
...@@ -32,8 +33,14 @@ public interface TasksSurface { ...@@ -32,8 +33,14 @@ public interface TasksSurface {
TabSwitcher.TabListDelegate getTabListDelegate(); TabSwitcher.TabListDelegate getTabListDelegate();
/** /**
* Get the container {@link ViewGroup} of the surface. * Get the view container {@link ViewGroup} of the tasks surface body.
* @return The surface's container {@link ViewGroup}. * @return The tasks surface body view container {@link ViewGroup}.
*/ */
ViewGroup getContainerView(); ViewGroup getBodyViewContainer();
/**
* Get the view {@link View} of the surface.
* @return The surface's container {@link View}.
*/
View getView();
} }
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package org.chromium.chrome.browser.tasks; package org.chromium.chrome.browser.tasks;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.LinearLayout; import android.widget.LinearLayout;
...@@ -34,10 +35,10 @@ public class TasksSurfaceCoordinator implements TasksSurface { ...@@ -34,10 +35,10 @@ public class TasksSurfaceCoordinator implements TasksSurface {
PropertyModelChangeProcessor.create(propertyModel, mView, TasksViewBinder::bind); PropertyModelChangeProcessor.create(propertyModel, mView, TasksViewBinder::bind);
if (isTabCarousel) { if (isTabCarousel) {
mTabSwitcher = TabManagementModuleProvider.getDelegate().createCarouselTabSwitcher( mTabSwitcher = TabManagementModuleProvider.getDelegate().createCarouselTabSwitcher(
activity, mView.getTabSwitcherContainer()); activity, mView.getCarouselTabSwitcherContainer());
} else { } else {
mTabSwitcher = TabManagementModuleProvider.getDelegate().createGridTabSwitcher( mTabSwitcher = TabManagementModuleProvider.getDelegate().createGridTabSwitcher(
activity, mView.getTabSwitcherContainer()); activity, mView.getBodyViewContainer());
} }
mMediator = mMediator =
...@@ -64,7 +65,12 @@ public class TasksSurfaceCoordinator implements TasksSurface { ...@@ -64,7 +65,12 @@ public class TasksSurfaceCoordinator implements TasksSurface {
} }
@Override @Override
public ViewGroup getContainerView() { public ViewGroup getBodyViewContainer() {
return mView.getBodyViewContainer();
}
@Override
public View getView() {
return mView; return mView;
} }
} }
...@@ -6,25 +6,27 @@ package org.chromium.chrome.browser.tasks; ...@@ -6,25 +6,27 @@ package org.chromium.chrome.browser.tasks;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.support.v4.view.MarginLayoutParamsCompat; import android.support.design.widget.AppBarLayout;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.browser.coordinator.CoordinatorLayoutForPointer;
import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.chrome.browser.util.ColorUtils;
import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.tab_ui.R;
// The view of the tasks surface. // The view of the tasks surface.
class TasksView extends LinearLayout { class TasksView extends CoordinatorLayoutForPointer {
private final Context mContext; private final Context mContext;
private FrameLayout mTabSwitcherContainer; private FrameLayout mBodyViewContainer;
private FrameLayout mCarouselTabSwitcherContainer;
private AppBarLayout mHeaderView;
private View mSearchBox; private View mSearchBox;
private TextView mSearchBoxText; private TextView mSearchBoxText;
...@@ -38,13 +40,22 @@ class TasksView extends LinearLayout { ...@@ -38,13 +40,22 @@ class TasksView extends LinearLayout {
protected void onFinishInflate() { protected void onFinishInflate() {
super.onFinishInflate(); super.onFinishInflate();
mTabSwitcherContainer = (FrameLayout) findViewById(R.id.tab_switcher_container); mCarouselTabSwitcherContainer =
(FrameLayout) findViewById(R.id.carousel_tab_switcher_container);
mSearchBox = findViewById(R.id.search_box); mSearchBox = findViewById(R.id.search_box);
mHeaderView = (AppBarLayout) findViewById(R.id.task_surface_header);
AppBarLayout.LayoutParams layoutParams =
(AppBarLayout.LayoutParams) mSearchBox.getLayoutParams();
layoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL);
mSearchBoxText = (TextView) mSearchBox.findViewById(R.id.search_box_text); mSearchBoxText = (TextView) mSearchBox.findViewById(R.id.search_box_text);
} }
ViewGroup getTabSwitcherContainer() { ViewGroup getCarouselTabSwitcherContainer() {
return mTabSwitcherContainer; return mCarouselTabSwitcherContainer;
}
ViewGroup getBodyViewContainer() {
return findViewById(R.id.tasks_surface_body);
} }
/** /**
...@@ -55,16 +66,7 @@ class TasksView extends LinearLayout { ...@@ -55,16 +66,7 @@ class TasksView extends LinearLayout {
if (isTabCarousel) { if (isTabCarousel) {
// TODO(crbug.com/982018): Change view according to incognito and dark mode. // TODO(crbug.com/982018): Change view according to incognito and dark mode.
findViewById(R.id.tab_switcher_title).setVisibility(View.VISIBLE); findViewById(R.id.tab_switcher_title).setVisibility(View.VISIBLE);
mCarouselTabSwitcherContainer.setVisibility(View.VISIBLE);
// Add negative margin to start so as to reduce the first Tab card's visual distance to
// the start edge to ~16dp.
// TODO(crbug.com/982018): Add test to guard the visual expectation.
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
MarginLayoutParamsCompat.setMarginStart(layoutParams,
mContext.getResources().getDimensionPixelSize(
R.dimen.tab_carousel_start_margin));
mTabSwitcherContainer.setLayoutParams(layoutParams);
} }
} }
...@@ -128,7 +130,9 @@ class TasksView extends LinearLayout { ...@@ -128,7 +130,9 @@ class TasksView extends LinearLayout {
*/ */
void setIncognitoMode(boolean isIncognito) { void setIncognitoMode(boolean isIncognito) {
Resources resources = mContext.getResources(); Resources resources = mContext.getResources();
setBackgroundColor(ColorUtils.getPrimaryBackgroundColor(resources, isIncognito)); int backgroundColor = ColorUtils.getPrimaryBackgroundColor(resources, isIncognito);
setBackgroundColor(backgroundColor);
mHeaderView.setBackgroundColor(backgroundColor);
mSearchBox.setBackgroundResource( mSearchBox.setBackgroundResource(
isIncognito ? R.drawable.fake_search_box_bg_incognito : R.drawable.ntp_search_box); isIncognito ? R.drawable.fake_search_box_bg_incognito : R.drawable.ntp_search_box);
int hintTextColor = isIncognito int hintTextColor = isIncognito
......
...@@ -44,4 +44,4 @@ class TasksViewBinder { ...@@ -44,4 +44,4 @@ class TasksViewBinder {
model.get(VOICE_SEARCH_BUTTON_CLICK_LISTENER)); model.get(VOICE_SEARCH_BUTTON_CLICK_LISTENER));
} }
} }
} }
\ No newline at end of file
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