Commit 2518c6f4 authored by Michael van Ouwerkerk's avatar Michael van Ouwerkerk Committed by Commit Bot

In new-tab-Chrome-Home put the logo inside the RecyclerView.

Bug: 781163
Change-Id: Id0957afdf125feeefb6dbfa36c9b3754552c735f
Reviewed-on: https://chromium-review.googlesource.com/759002
Commit-Queue: Michael van Ouwerkerk <mvanouwerkerk@chromium.org>
Reviewed-by: default avatarBernhard Bauer <bauerb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#515591}
parent c4af4315
......@@ -13,15 +13,5 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:paddingTop="@dimen/bottom_control_container_height"
android:clipToPadding="false" />
<!-- The logo should be rendered on top of the RecyclerView, so it goes below in code order. -->
<org.chromium.chrome.browser.ntp.LogoView
android:id="@+id/search_provider_logo"
android:layout_width="match_parent"
android:layout_height="@dimen/ntp_logo_height"
android:layout_marginTop="@dimen/ntp_logo_margin_top_modern"
android:layout_marginBottom="@dimen/ntp_logo_margin_bottom_modern" />
android:paddingTop="@dimen/bottom_control_container_height" />
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2017 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. -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/ntp_logo_height">
<org.chromium.chrome.browser.ntp.LogoView
android:id="@+id/search_provider_logo"
android:layout_width="match_parent"
android:layout_height="@dimen/ntp_logo_height"
android:layout_marginTop="@dimen/ntp_logo_margin_top_modern"
android:layout_marginBottom="@dimen/ntp_logo_margin_bottom_modern" />
</FrameLayout>
\ No newline at end of file
......@@ -326,7 +326,8 @@
<dimen name="tile_view_title_margin_top_modern">61dp</dimen>
<dimen name="ntp_logo_height">116dp</dimen>
<dimen name="ntp_logo_margin_top_modern">25dp</dimen>
<dimen name="ntp_logo_margin_bottom_modern">8dp</dimen>
<!-- bottom_control_container_height + 8 -->
<dimen name="ntp_logo_margin_bottom_modern">64dp</dimen>
<dimen name="ntp_search_box_height">62dp</dimen>
<dimen name="ntp_search_box_shadow_width">4dp</dimen>
<dimen name="ntp_search_box_transition_length">16dp</dimen>
......
......@@ -303,9 +303,10 @@ public class NewTabPageView extends FrameLayout implements TileGroup.Observer {
mRecyclerView.init(mUiConfig, mContextMenuManager);
// Set up snippets
NewTabPageAdapter newTabPageAdapter = new NewTabPageAdapter(mManager, mNewTabPageLayout,
mUiConfig, offlinePageBridge, mContextMenuManager, /* tileGroupDelegate = */ null,
/* suggestionsCarousel = */ null);
NewTabPageAdapter newTabPageAdapter =
new NewTabPageAdapter(mManager, mNewTabPageLayout, /* logoView = */ null, mUiConfig,
offlinePageBridge, mContextMenuManager, /* tileGroupDelegate = */ null,
/* suggestionsCarousel = */ null);
newTabPageAdapter.refreshSuggestions();
mRecyclerView.setAdapter(newTabPageAdapter);
mRecyclerView.getLinearLayoutManager().scrollToPosition(scrollPosition);
......
......@@ -17,10 +17,10 @@ import java.lang.annotation.RetentionPolicy;
*
* @see Adapter#getItemViewType(int)
*/
@IntDef({ItemViewType.ABOVE_THE_FOLD, ItemViewType.SITE_SECTION, ItemViewType.HEADER,
ItemViewType.SNIPPET, ItemViewType.SPACING, ItemViewType.STATUS, ItemViewType.PROGRESS,
ItemViewType.ACTION, ItemViewType.FOOTER, ItemViewType.PROMO, ItemViewType.ALL_DISMISSED,
ItemViewType.CAROUSEL})
@IntDef({ItemViewType.ABOVE_THE_FOLD, ItemViewType.LOGO, ItemViewType.SITE_SECTION,
ItemViewType.HEADER, ItemViewType.SNIPPET, ItemViewType.SPACING, ItemViewType.STATUS,
ItemViewType.PROGRESS, ItemViewType.ACTION, ItemViewType.FOOTER, ItemViewType.PROMO,
ItemViewType.ALL_DISMISSED, ItemViewType.CAROUSEL})
@Retention(RetentionPolicy.SOURCE)
public @interface ItemViewType {
/**
......@@ -29,71 +29,77 @@ public @interface ItemViewType {
* @see Adapter#getItemViewType(int)
*/
int ABOVE_THE_FOLD = 1;
/**
* View type for the logo
*
* @see Adapter#getItemViewType(int)
*/
int LOGO = 2;
/**
* View type for a {@code SiteSection}.
*
* @see Adapter#getItemViewType(int)
*/
int SITE_SECTION = 2;
int SITE_SECTION = 3;
/**
* View type for card group headers
*
* @see Adapter#getItemViewType(int)
*/
int HEADER = 3;
int HEADER = 4;
/**
* View type for snippet cards
*
* @see Adapter#getItemViewType(int)
*/
int SNIPPET = 4;
int SNIPPET = 5;
/**
* View type for a {@link SpacingItem} used to provide spacing at the end of the list.
*
* @see Adapter#getItemViewType(int)
*/
int SPACING = 5;
int SPACING = 6;
/**
* View type for a {@link StatusItem}, the card displaying status information
*
* @see Adapter#getItemViewType(int)
*/
int STATUS = 6;
int STATUS = 7;
/**
* View type for a {@link ProgressItem}, the progress indicator.
*
* @see Adapter#getItemViewType(int)
*/
int PROGRESS = 7;
int PROGRESS = 8;
/**
* View type for a {@link ActionItem}, an action button.
*
* @see Adapter#getItemViewType(int)
*/
int ACTION = 8;
int ACTION = 9;
/**
* View type for a {@link Footer}.
*
* @see Adapter#getItemViewType(int)
*/
int FOOTER = 9;
int FOOTER = 10;
/**
* View type for a {@link SignInPromo}.
*
* @see Adapter#getItemViewType(int)
*/
int PROMO = 10;
int PROMO = 11;
/**
* View type for a {@link AllDismissedItem}.
*
* @see Adapter#getItemViewType(int)
*/
int ALL_DISMISSED = 11;
int ALL_DISMISSED = 12;
/**
* View type for a {@link SuggestionsCarousel}.
*
* @see Adapter#getItemViewType(int)
*/
int CAROUSEL = 12;
int CAROUSEL = 13;
}
......@@ -14,6 +14,7 @@ import org.chromium.base.Callback;
import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.ntp.ContextMenuManager;
import org.chromium.chrome.browser.ntp.LogoView;
import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder.PartialBindCallback;
import org.chromium.chrome.browser.ntp.snippets.CategoryInt;
import org.chromium.chrome.browser.ntp.snippets.CategoryStatus;
......@@ -24,6 +25,7 @@ import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge;
import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource;
import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
import org.chromium.chrome.browser.suggestions.DestructionObserver;
import org.chromium.chrome.browser.suggestions.LogoItem;
import org.chromium.chrome.browser.suggestions.SiteSection;
import org.chromium.chrome.browser.suggestions.SuggestionsCarousel;
import org.chromium.chrome.browser.suggestions.SuggestionsConfig;
......@@ -47,17 +49,16 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder> implements
private final ContextMenuManager mContextMenuManager;
private final OfflinePageBridge mOfflinePageBridge;
@Nullable
private final View mAboveTheFoldView;
private final @Nullable View mAboveTheFoldView;
private final @Nullable LogoView mLogoView;
private final UiConfig mUiConfig;
private SuggestionsRecyclerView mRecyclerView;
private final InnerNode mRoot;
@Nullable
private final AboveTheFoldItem mAboveTheFold;
@Nullable
private final SiteSection mSiteSection;
private final @Nullable AboveTheFoldItem mAboveTheFold;
private final @Nullable LogoItem mLogo;
private final @Nullable SiteSection mSiteSection;
private final SuggestionsCarousel mSuggestionsCarousel;
private final SectionList mSections;
private final SignInPromo mSigninPromo;
......@@ -71,6 +72,9 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder> implements
* @param aboveTheFoldView the layout encapsulating all the above-the-fold elements
* (logo, search box, most visited tiles), or null if only suggestions should
* be displayed.
* @param logoView the view for the logo, which may be provided when {@code aboveTheFoldView} is
* null. They are not expected to be both non-null as that would lead to showing the
* logo twice.
* @param uiConfig the NTP UI configuration, to be passed to created views.
* @param offlinePageBridge used to determine if articles are available.
* @param contextMenuManager used to build context menus.
......@@ -79,13 +83,16 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder> implements
* suggestions.
*/
public NewTabPageAdapter(SuggestionsUiDelegate uiDelegate, @Nullable View aboveTheFoldView,
UiConfig uiConfig, OfflinePageBridge offlinePageBridge,
@Nullable LogoView logoView, UiConfig uiConfig, OfflinePageBridge offlinePageBridge,
ContextMenuManager contextMenuManager, @Nullable TileGroup.Delegate tileGroupDelegate,
@Nullable SuggestionsCarousel suggestionsCarousel) {
assert !(aboveTheFoldView != null && logoView != null);
mUiDelegate = uiDelegate;
mContextMenuManager = contextMenuManager;
mAboveTheFoldView = aboveTheFoldView;
mLogoView = logoView;
mUiConfig = uiConfig;
mRoot = new InnerNode();
mSections = new SectionList(mUiDelegate, offlinePageBridge);
......@@ -99,6 +106,13 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder> implements
mRoot.addChild(mAboveTheFold);
}
if (mLogoView == null) {
mLogo = null;
} else {
mLogo = new LogoItem();
mRoot.addChild(mLogo);
}
mSuggestionsCarousel = suggestionsCarousel;
if (suggestionsCarousel != null) {
assert ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_SUGGESTIONS_CAROUSEL);
......@@ -153,6 +167,9 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder> implements
case ItemViewType.ABOVE_THE_FOLD:
return new NewTabPageViewHolder(mAboveTheFoldView);
case ItemViewType.LOGO:
return new NewTabPageViewHolder(mLogoView);
case ItemViewType.SITE_SECTION:
return SiteSection.createViewHolder(
SiteSection.inflateSiteSection(parent), mUiConfig);
......@@ -362,6 +379,15 @@ public class NewTabPageAdapter extends Adapter<NewTabPageViewHolder> implements
mRoot.dismissItem(position, itemRemovedCallback);
}
/**
* Sets the visibility of the logo.
* @param visible Whether the logo should be visible.
*/
public void setLogoVisibility(boolean visible) {
assert mLogo != null;
mLogo.setVisible(visible);
}
/**
* Drops all but the first {@code n} thumbnails on articles.
* @param n The number of article thumbnails to keep.
......
......@@ -76,7 +76,7 @@ public class NodeVisitor {
public void visitCarouselItem(SuggestionsCarouselAdapter adapter) {}
/**
* Visits a card placeholder item.
* Visits a logo.
*/
public void visitPlaceholderItem() {}
public void visitLogo() {}
}
// Copyright 2017 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.
package org.chromium.chrome.browser.suggestions;
import org.chromium.chrome.browser.ntp.cards.ItemViewType;
import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder;
import org.chromium.chrome.browser.ntp.cards.NodeVisitor;
import org.chromium.chrome.browser.ntp.cards.OptionalLeaf;
/**
* A logo for the search engine provider.
*/
public class LogoItem extends OptionalLeaf {
@Override
@ItemViewType
protected int getItemViewType() {
return ItemViewType.LOGO;
}
@Override
protected void onBindViewHolder(NewTabPageViewHolder holder) {}
@Override
public void visitOptionalItem(NodeVisitor visitor) {
visitor.visitLogo();
}
public void setVisible(boolean visible) {
setVisibilityInternal(visible);
}
}
......@@ -15,6 +15,7 @@ import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import org.chromium.base.CollectionUtil;
import org.chromium.chrome.R;
......@@ -57,6 +58,7 @@ public class SuggestionsBottomSheetContent implements BottomSheet.BottomSheetCon
private final View mView;
private final SuggestionsRecyclerView mRecyclerView;
private final NewTabPageAdapter mAdapter;
private final ContextMenuManager mContextMenuManager;
private final SuggestionsUiDelegateImpl mSuggestionsUiDelegate;
private final TileGroup.Delegate mTileGroupDelegate;
......@@ -123,7 +125,8 @@ public class SuggestionsBottomSheetContent implements BottomSheet.BottomSheetCon
mToolbarHeight = resources.getDimensionPixelSize(R.dimen.bottom_control_container_height);
mMaxToolbarOffset = resources.getDimensionPixelSize(R.dimen.ntp_logo_height)
+ resources.getDimensionPixelSize(R.dimen.ntp_logo_margin_top_modern)
+ resources.getDimensionPixelSize(R.dimen.ntp_logo_margin_bottom_modern);
+ resources.getDimensionPixelSize(R.dimen.ntp_logo_margin_bottom_modern)
- mToolbarHeight;
TouchEnabledDelegate touchEnabledDelegate = activity.getBottomSheet()::setTouchEnabled;
mContextMenuManager = new ContextMenuManager(
......@@ -144,9 +147,15 @@ public class SuggestionsBottomSheetContent implements BottomSheet.BottomSheetCon
uiConfig, mSuggestionsUiDelegate, mContextMenuManager, offlinePageBridge)
: null;
final NewTabPageAdapter adapter = new NewTabPageAdapter(mSuggestionsUiDelegate,
/* aboveTheFoldView = */ null, uiConfig, offlinePageBridge, mContextMenuManager,
mTileGroupDelegate, mSuggestionsCarousel);
// Inflate the logo in a container so its layout attributes are applied, then take it out.
FrameLayout logoContainer = (FrameLayout) LayoutInflater.from(activity).inflate(
R.layout.suggestions_bottom_sheet_logo, null);
mLogoView = logoContainer.findViewById(R.id.search_provider_logo);
logoContainer.removeView(mLogoView);
mAdapter = new NewTabPageAdapter(mSuggestionsUiDelegate,
/* aboveTheFoldView = */ null, mLogoView, uiConfig, offlinePageBridge,
mContextMenuManager, mTileGroupDelegate, mSuggestionsCarousel);
mBottomSheetObserver = new SuggestionsSheetVisibilityChangeObserver(this, activity) {
@Override
......@@ -159,14 +168,14 @@ public class SuggestionsBottomSheetContent implements BottomSheet.BottomSheetCon
SuggestionsMetrics.recordSurfaceVisible();
if (isFirstShown) {
adapter.refreshSuggestions();
mAdapter.refreshSuggestions();
maybeUpdateContextualSuggestions();
// Set the adapter on the RecyclerView after updating it, to avoid sending
// notifications that might confuse its internal state.
// See https://crbug.com/756514.
mRecyclerView.setAdapter(adapter);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.scrollToPosition(0);
mRecyclerView.getScrollEventReporter().reset();
}
......@@ -196,7 +205,7 @@ public class SuggestionsBottomSheetContent implements BottomSheet.BottomSheetCon
if (ChromeFeatureList.isEnabled(
ChromeFeatureList.CHROME_HOME_DROP_ALL_BUT_FIRST_THUMBNAIL)) {
adapter.dropAllButFirstNArticleThumbnails(1);
mAdapter.dropAllButFirstNArticleThumbnails(1);
}
mRecyclerView.setAdapter(null);
updateLogoTransition();
......@@ -221,7 +230,6 @@ public class SuggestionsBottomSheetContent implements BottomSheet.BottomSheetCon
mView.setOnTouchListener(touchListener);
mRecyclerView.setOnTouchListener(touchListener);
mLogoView = mView.findViewById(R.id.search_provider_logo);
mControlContainerView = (ViewGroup) activity.findViewById(R.id.control_container);
mToolbarPullHandle = activity.findViewById(R.id.toolbar_handle);
mToolbarShadow = activity.findViewById(R.id.bottom_toolbar_shadow);
......@@ -320,20 +328,20 @@ public class SuggestionsBottomSheetContent implements BottomSheet.BottomSheetCon
@Override
public void onNewTabShown() {
mNewTabShown = true;
updateSpacing();
updateLogoVisibility();
}
@Override
public void onNewTabHidden() {
mNewTabShown = false;
updateSpacing();
updateLogoVisibility();
}
@Override
public void onTemplateURLServiceChanged() {
updateSearchProviderHasLogo();
loadSearchProviderLogo();
updateSpacing();
updateLogoVisibility();
updateLogoTransition();
}
......@@ -390,8 +398,6 @@ public class SuggestionsBottomSheetContent implements BottomSheet.BottomSheetCon
// If the logo is not shown, reset all transitions.
if (!showLogo) {
mLogoView.setTranslationY(0);
mLogoView.setVisibility(View.GONE);
mControlContainerView.setTranslationY(0);
mToolbarPullHandle.setTranslationY(0);
mToolbarShadow.setTranslationY(0);
......@@ -420,9 +426,6 @@ public class SuggestionsBottomSheetContent implements BottomSheet.BottomSheetCon
mTransitionFraction = 1.0f;
}
mLogoView.setTranslationY(-mMaxToolbarOffset * mTransitionFraction);
if (mLogoView.getVisibility() != View.VISIBLE) mLogoView.setVisibility(View.VISIBLE);
// Transform the sheet height fraction back to pixel scale.
float rangePx =
(mSheet.getFullRatio() - mSheet.getPeekRatio()) * mSheet.getSheetContainerHeight();
......@@ -436,6 +439,8 @@ public class SuggestionsBottomSheetContent implements BottomSheet.BottomSheetCon
mToolbarPullHandle.setTranslationY(-toolbarOffset);
mToolbarShadow.setTranslationY(-toolbarOffset);
// Fade out the whole RecyclerView when the URL bar is focused, and fade it in when it loses
// focus.
final float alpha;
if (isAnimating() && hasFocus) {
alpha = 1.0f - mAnimator.getAnimatedFraction();
......@@ -450,9 +455,10 @@ public class SuggestionsBottomSheetContent implements BottomSheet.BottomSheetCon
mRecyclerView.setVisibility(alpha == 0.0f ? View.INVISIBLE : View.VISIBLE);
}
private void updateSpacing() {
int top = mToolbarHeight;
if (shouldShowLogo()) top += (int) mMaxToolbarOffset;
private void updateLogoVisibility() {
boolean showLogo = shouldShowLogo();
mAdapter.setLogoVisibility(showLogo);
int top = showLogo ? 0 : mToolbarHeight;
int left = mRecyclerView.getPaddingLeft();
int right = mRecyclerView.getPaddingRight();
int bottom = mRecyclerView.getPaddingBottom();
......
......@@ -1069,6 +1069,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/suggestions/ContextualSuggestionsCardViewHolder.java",
"java/src/org/chromium/chrome/browser/suggestions/DestructionObserver.java",
"java/src/org/chromium/chrome/browser/suggestions/ImageFetcher.java",
"java/src/org/chromium/chrome/browser/suggestions/LogoItem.java",
"java/src/org/chromium/chrome/browser/suggestions/MostVisitedSites.java",
"java/src/org/chromium/chrome/browser/suggestions/MostVisitedSitesBridge.java",
"java/src/org/chromium/chrome/browser/suggestions/SiteSection.java",
......
......@@ -282,7 +282,7 @@ public class NewTabPageAdapterTest {
FeatureUtilities.resetChromeHomeEnabledForTests();
// Set empty variation params for the test.
CardsVariationParameters.setTestVariationParams(new HashMap<>());
CardsVariationParameters.setTestVariationParams(new HashMap<String, String>());
// Initialise the sign in state. We will be signed in by default in the tests.
assertFalse(
......@@ -1259,7 +1259,7 @@ public class NewTabPageAdapterTest {
*/
private SectionDescriptor sectionWithStatusCard() {
assertFalse(FeatureUtilities.isChromeHomeEnabled());
return new SectionDescriptor(Collections.emptyList()).withStatusCard();
return new SectionDescriptor(Collections.<SnippetArticle>emptyList()).withStatusCard();
}
/**
......@@ -1270,7 +1270,7 @@ public class NewTabPageAdapterTest {
*/
private SectionDescriptor emptySection() {
assertTrue(FeatureUtilities.isChromeHomeEnabled());
return new SectionDescriptor(Collections.emptyList());
return new SectionDescriptor(Collections.<SnippetArticle>emptyList());
}
private void resetUiDelegate() {
......@@ -1282,8 +1282,8 @@ public class NewTabPageAdapterTest {
private void reloadNtp() {
mSource.removeObservers();
mAdapter = new NewTabPageAdapter(mUiDelegate, mock(View.class), makeUiConfig(),
mOfflinePageBridge, mock(ContextMenuManager.class),
mAdapter = new NewTabPageAdapter(mUiDelegate, mock(View.class), /* logoView = */ null,
makeUiConfig(), mOfflinePageBridge, mock(ContextMenuManager.class),
/* tileGroupDelegate = */ null, /* suggestionsCarousel = */ null);
mAdapter.refreshSuggestions();
}
......
......@@ -198,8 +198,8 @@ public final class ContentSuggestionsTestUtils {
}
@Override
public void visitPlaceholderItem() {
describeItem("PLACEHOLDER_CARD");
public void visitLogo() {
describeItem("LOGO");
}
private void describeItem(String description) {
......
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