Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4527)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java

Issue 1947263003: Pin the snippets to the bottom of the page and introduce a peeking card to indicate to the user the… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
index 58b58b1ecf6771307c3912d3827895a7bb237942..a475a02933141b8f62fb55d146228023c538bb06 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -45,6 +45,7 @@ import org.chromium.chrome.browser.ntp.LogoBridge.LogoObserver;
import org.chromium.chrome.browser.ntp.MostVisitedItem.MostVisitedItemManager;
import org.chromium.chrome.browser.ntp.NewTabPage.OnSearchBoxScrollListener;
import org.chromium.chrome.browser.ntp.cards.NewTabPageAdapter;
+import org.chromium.chrome.browser.ntp.cards.NewTabPageListItem;
import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView;
import org.chromium.chrome.browser.ntp.snippets.SnippetArticle;
import org.chromium.chrome.browser.ntp.snippets.SnippetItemDecoration;
@@ -76,14 +77,14 @@ public class NewTabPageView extends FrameLayout
* Indicates which UI mode we are using. Should be checked when manipulating some members, as
* they may be unused or {@code null} depending on the mode.
*/
- private boolean mUseCardsUi;
+ private static boolean USE_CARDS_UI;
May 2016/05/05 16:28:22 ALL_CAPS only for static final, otherwise use sAbc
Bernhard Bauer 2016/05/05 16:46:04 SHOUTING_CASE is only used for constants (which ar
mcwilliams 2016/05/05 17:39:47 Done.
mcwilliams 2016/05/05 17:39:47 Done.
// Note: Only one of these will be valid at a time, depending on if we are using the old NTP
// (NewTabPageScrollView) or the new NTP with cards (NewTabPageRecyclerView).
private NewTabPageScrollView mScrollView;
private NewTabPageRecyclerView mRecyclerView;
- private NewTabPageLayout mContentView;
+ private NewTabPageLayout mNewTabPageLayout;
private LogoView mSearchProviderLogoView;
private View mSearchBoxView;
private ImageView mVoiceSearchButton;
@@ -92,7 +93,7 @@ public class NewTabPageView extends FrameLayout
private View mNoSearchLogoSpacer;
/** Adapter for {@link #mRecyclerView}. Will be {@code null} when using the old UI */
- private NewTabPageAdapter mNtpAdapter;
+ private NewTabPageAdapter mNewTabPageAdapter;
private OnSearchBoxScrollListener mSearchBoxScrollListener;
@@ -119,6 +120,8 @@ public class NewTabPageView extends FrameLayout
private int mSnapshotHeight;
private int mSnapshotScrollY;
+ private int peekingCardVerticalScrollStart;
May 2016/05/05 16:28:22 Unused variable?
Bernhard Bauer 2016/05/05 16:46:04 Member variables should start with "m" (and contin
mcwilliams 2016/05/05 17:39:46 Done.
mcwilliams 2016/05/05 17:39:47 Very much used
+
/**
* Manages the view interaction with the rest of the system.
*/
@@ -271,34 +274,36 @@ public class NewTabPageView extends FrameLayout
mManager = manager;
ViewStub stub = (ViewStub) findViewById(R.id.new_tab_page_layout_stub);
- mUseCardsUi = useCardsUi;
- if (mUseCardsUi) {
+ USE_CARDS_UI = useCardsUi;
+ if (USE_CARDS_UI) {
stub.setLayoutResource(R.layout.new_tab_page_recycler_view);
mRecyclerView = (NewTabPageRecyclerView) stub.inflate();
// Don't attach now, the recyclerView itself will determine when to do it.
- mContentView = (NewTabPageLayout) LayoutInflater.from(getContext())
- .inflate(R.layout.new_tab_page_layout, mRecyclerView, false);
+ mNewTabPageLayout =
+ (NewTabPageLayout) LayoutInflater.from(getContext())
+ .inflate(R.layout.new_tab_page_layout, mRecyclerView, false);
// Tailor the LayoutParams for the snippets UI, as the configuration in the XML is
// made for the ScrollView UI.
- ViewGroup.LayoutParams params = mContentView.getLayoutParams();
+ ViewGroup.LayoutParams params = mNewTabPageLayout.getLayoutParams();
params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
} else {
stub.setLayoutResource(R.layout.new_tab_page_scroll_view);
mScrollView = (NewTabPageScrollView) stub.inflate();
mScrollView.enableBottomShadow(SHADOW_COLOR);
- mContentView = (NewTabPageLayout) findViewById(R.id.ntp_content);
+ mNewTabPageLayout = (NewTabPageLayout) findViewById(R.id.ntp_content);
}
mMostVisitedDesign = new MostVisitedDesign(getContext());
mMostVisitedLayout =
- (MostVisitedLayout) mContentView.findViewById(R.id.most_visited_layout);
+ (MostVisitedLayout) mNewTabPageLayout.findViewById(R.id.most_visited_layout);
mMostVisitedDesign.initMostVisitedLayout(mMostVisitedLayout, searchProviderHasLogo);
- mSearchProviderLogoView = (LogoView) mContentView.findViewById(R.id.search_provider_logo);
- mSearchBoxView = mContentView.findViewById(R.id.search_box);
- mNoSearchLogoSpacer = mContentView.findViewById(R.id.no_search_logo_spacer);
+ mSearchProviderLogoView =
+ (LogoView) mNewTabPageLayout.findViewById(R.id.search_provider_logo);
+ mSearchBoxView = mNewTabPageLayout.findViewById(R.id.search_box);
+ mNoSearchLogoSpacer = mNewTabPageLayout.findViewById(R.id.no_search_logo_spacer);
final TextView searchBoxTextView = (TextView) mSearchBoxView
.findViewById(R.id.search_box_text);
@@ -332,7 +337,7 @@ public class NewTabPageView extends FrameLayout
}
});
- mVoiceSearchButton = (ImageView) mContentView.findViewById(R.id.voice_search_button);
+ mVoiceSearchButton = (ImageView) mNewTabPageLayout.findViewById(R.id.voice_search_button);
mVoiceSearchButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -368,7 +373,7 @@ public class NewTabPageView extends FrameLayout
}
} else {
((ViewGroup) toolbar.getParent()).removeView(toolbar);
- if (!mUseCardsUi) {
+ if (!USE_CARDS_UI) {
// Only remove if we're using the old NTP view, the new one does not use a
// ScrollView
FrameLayout.LayoutParams params =
@@ -386,12 +391,14 @@ public class NewTabPageView extends FrameLayout
mMostVisitedDesign.getNumberOfTiles(searchProviderHasLogo));
// Set up snippets
- if (mUseCardsUi) {
- mNtpAdapter = new NewTabPageAdapter(mManager, mContentView);
- mRecyclerView.setAdapter(mNtpAdapter);
+ if (USE_CARDS_UI) {
+ mNewTabPageAdapter = new NewTabPageAdapter(mManager, mNewTabPageLayout);
+ mRecyclerView.setAdapter(mNewTabPageAdapter);
+ mRecyclerView.setNewTabPageLayout(mNewTabPageLayout);
May 2016/05/05 16:28:22 I don't think this is necessary anymore
mcwilliams 2016/05/05 17:39:47 Done.
// Set up swipe-to-dismiss
- ItemTouchHelper helper = new ItemTouchHelper(mNtpAdapter.getItemTouchCallbacks());
+ ItemTouchHelper helper =
+ new ItemTouchHelper(mNewTabPageAdapter.getItemTouchCallbacks());
helper.attachToRecyclerView(mRecyclerView);
NewTabPageUma.recordSnippetAction(NewTabPageUma.SNIPPETS_ACTION_SHOWN);
@@ -408,6 +415,7 @@ public class NewTabPageView extends FrameLayout
});
initializeSearchBoxRecyclerViewScrollHandling();
mRecyclerView.addItemDecoration(new SnippetItemDecoration());
+ updatePeekingCard();
} else {
initializeSearchBoxScrollHandling();
}
@@ -419,12 +427,12 @@ public class NewTabPageView extends FrameLayout
float percentage = 0;
// During startup the view may not be fully initialized, so we only calculate the current
// percentage if some basic view properties are sane.
- View wrapperView = mUseCardsUi ? mRecyclerView : mScrollView;
+ View wrapperView = USE_CARDS_UI ? mRecyclerView : mScrollView;
if (wrapperView.getHeight() != 0 && mSearchBoxView.getTop() != 0) {
// getVerticalScroll is valid only for the RecyclerView if the first item is visible.
// Luckily, if the first item is not visible, we know the toolbar transition should
// be 100%.
- if (mUseCardsUi && !mRecyclerView.isFirstItemVisible()) {
+ if (USE_CARDS_UI && !mRecyclerView.isFirstItemVisible()) {
percentage = 1f;
} else {
int scrollY = getVerticalScroll();
@@ -439,6 +447,52 @@ public class NewTabPageView extends FrameLayout
}
}
+ /**
+ * Calculate the peeking card/first snippet bleed and padding when scrolling if it is visible.
+ */
+ private void updatePeekingCard() {
Bernhard Bauer 2016/05/05 16:46:04 updatePeekingCardOnScroll()?
mcwilliams 2016/05/05 17:39:46 It is not just on scroll but also on initialize
+ // Get the first snippet that could display to make the peeking card transition.
+ View firstSnippetView = null;
+ int recyclerViewSize = mNewTabPageAdapter.getItemCount();
May 2016/05/05 16:28:22 Not really the recyclerViewSize, it's the adapterS
mcwilliams 2016/05/05 17:39:46 Done.
+ for (int i = 0; i < recyclerViewSize; i++) {
+ if (mNewTabPageAdapter.getItemViewType(i) == NewTabPageListItem.VIEW_TYPE_SNIPPET) {
+ firstSnippetView = mRecyclerView.getLayoutManager().findViewByPosition(i);
+ break;
+ }
+ }
+
+ // If first snippet exists change the parameters from peeking card with bleed to full page
+ // card when scrolling.
+ if (firstSnippetView != null && firstSnippetView.isShown()) {
+ // Value used for max peeking card height and padding.
+ int maxPadding = mNewTabPageLayout.getContext().getResources().getDimensionPixelSize(
PEConn 2016/05/05 16:31:28 mNewTabPageLayout.getContext().getResources() can
mcwilliams 2016/05/05 17:39:46 Done.
+ R.dimen.snippets_padding_and_peeking_card_height);
+
+ // As the user scrolls, the bleed increases or decreases.
+ int bleed = maxPadding - (getVerticalScroll() - peekingCardVerticalScrollStart);
+
+ // Never let the bleed go into negative digits.
+ bleed = Math.max(bleed, 0);
+ // Never let the bleed be greater than the maxPadding.
+ bleed = Math.min(bleed, maxPadding);
+
+ // Modify the padding so as the margin increases, the padding decreases so the cards
+ // content does not shift.
+ firstSnippetView.setPadding(
+ maxPadding - bleed, maxPadding, maxPadding - bleed, maxPadding);
PEConn 2016/05/05 16:31:28 Maybe add a comment that the 2nd and 4th arguments
mcwilliams 2016/05/05 17:39:46 Done.
+
+ // Modify the margin to grow the card from bleed to full width.
+ RecyclerView.LayoutParams params =
+ (RecyclerView.LayoutParams) firstSnippetView.getLayoutParams();
+ params.leftMargin = bleed;
+ params.rightMargin = bleed;
+ }
+ }
+
+ /**
+ * Sets up scrolling when snippets are enabled. It adds scroll listeners and touch listeners to
PEConn 2016/05/05 16:31:28 I'd argue this comment is a bit too indepth - the
mcwilliams 2016/05/05 17:39:47 Acknowledged.
+ * the RecyclerView.
+ */
private void initializeSearchBoxRecyclerViewScrollHandling() {
final Runnable mSnapScrollRunnable = new Runnable() {
@Override
@@ -449,13 +503,14 @@ public class NewTabPageView extends FrameLayout
// computeVerticalScrollOffset only takes into account visible items).
// Luckily, we only need to perform the calculations if the first item is visible.
if (!mRecyclerView.isFirstItemVisible()) return;
+
final int currentScroll = mRecyclerView.computeVerticalScrollOffset();
// If snapping to Most Likely or to Articles, the omnibox will be at the top of the
// page, so offset the scroll so the scroll targets appear below it.
- final int omniBoxHeight = mContentView.getPaddingTop();
+ final int omniBoxHeight = mNewTabPageLayout.getPaddingTop();
final int topOfMostLikelyScroll = mMostVisitedLayout.getTop() - omniBoxHeight;
- final int topOfSnippetsScroll = mContentView.getHeight() - omniBoxHeight;
+ final int topOfSnippetsScroll = mNewTabPageLayout.getHeight() - omniBoxHeight;
assert currentScroll >= 0;
// Do not do any scrolling if the user is currently viewing articles.
@@ -468,10 +523,11 @@ public class NewTabPageView extends FrameLayout
mRecyclerView.getHeight() < mMostVisitedLayout.getBottom();
int targetScroll;
- if (currentScroll < mContentView.getHeight() / 3) {
+ if (currentScroll < mNewTabPageLayout.getHeight() / 3) {
// In either case, if in the top 1/3 of the original NTP, snap to the top.
targetScroll = 0;
- } else if (snapToMostLikely && currentScroll < mContentView.getHeight() * 2 / 3) {
+ } else if (
+ snapToMostLikely && currentScroll < mNewTabPageLayout.getHeight() * 2 / 3) {
May 2016/05/05 16:28:22 unnecessary line break
mcwilliams 2016/05/05 17:39:47 If I don't line break it is over 100 chars?
Bernhard Bauer 2016/05/05 18:04:40 I think what May meant was that breaking right aft
mcwilliams 2016/05/05 18:21:11 Done.
// If in the middle 1/3 and we are snapping to Most Likely, snap to it.
targetScroll = topOfMostLikelyScroll;
} else {
@@ -480,6 +536,10 @@ public class NewTabPageView extends FrameLayout
}
mRecyclerView.smoothScrollBy(0, targetScroll - currentScroll);
+
+ // Set the peeking card vertical scroll start for the snapped view.
+ peekingCardVerticalScrollStart = targetScroll;
+
mPendingSnapScroll = false;
}
};
@@ -492,6 +552,7 @@ public class NewTabPageView extends FrameLayout
mRecyclerView.postDelayed(mSnapScrollRunnable, SNAP_SCROLL_DELAY_MS);
}
updateSearchBoxOnScroll();
+ updatePeekingCard();
}
});
@@ -513,13 +574,17 @@ public class NewTabPageView extends FrameLayout
});
}
+ /**
+ * Sets up scrolling when snippets are disabled. It ads scroll and touch listeners to the scroll
PEConn 2016/05/05 16:31:28 *adds
Bernhard Bauer 2016/05/05 16:46:04 Nit: "adds"
mcwilliams 2016/05/05 17:39:47 Done.
mcwilliams 2016/05/05 17:39:47 Done.
+ * view.
+ */
private void initializeSearchBoxScrollHandling() {
final Runnable mSnapScrollRunnable = new Runnable() {
@Override
public void run() {
if (!mPendingSnapScroll) return;
int scrollY = mScrollView.getScrollY();
- int dividerTop = mMostVisitedLayout.getTop() - mContentView.getPaddingTop();
+ int dividerTop = mMostVisitedLayout.getTop() - mNewTabPageLayout.getPaddingTop();
if (scrollY > 0 && scrollY < dividerTop) {
mScrollView.smoothScrollTo(0, scrollY < (dividerTop / 2) ? 0 : dividerTop);
}
@@ -603,9 +668,9 @@ public class NewTabPageView extends FrameLayout
// Hide or show all the views above the Most Visited items.
int visibility = hasLogo ? View.VISIBLE : View.GONE;
- int childCount = mContentView.getChildCount();
+ int childCount = mNewTabPageLayout.getChildCount();
for (int i = 0; i < childCount; i++) {
- View child = mContentView.getChildAt(i);
+ View child = mNewTabPageLayout.getChildAt(i);
if (child == mMostVisitedLayout) break;
// Don't change the visibility of a ViewStub as that will automagically inflate it.
if (child instanceof ViewStub) continue;
@@ -687,12 +752,16 @@ public class NewTabPageView extends FrameLayout
// Only apply the scrolling offset when not using the cards UI, as there we will either snap
// to the top of the page (with scrolling offset 0), or snap to below the fold, where Most
// Likely items are not visible anymore, so they will stay out of sight.
- int scrollOffset = mUseCardsUi ? 0 : mScrollView.getScrollY();
- mContentView.setTranslationY(percent
- * (-mMostVisitedLayout.getTop() + scrollOffset + mContentView.getPaddingTop()));
+ int scrollOffset = USE_CARDS_UI ? 0 : mScrollView.getScrollY();
+ mNewTabPageLayout.setTranslationY(percent * (-mMostVisitedLayout.getTop() + scrollOffset
+ + mNewTabPageLayout.getPaddingTop()));
updateVisualsForToolbarTransition(percent);
}
+ /**
+ * Updates the opacity of the fake omnibox and Google logo when scrolling.
+ * @param transitionPercentage
+ */
private void updateVisualsForToolbarTransition(float transitionPercentage) {
// Complete the full alpha transition in the first 40% of the animation.
float searchUiAlpha =
@@ -893,7 +962,7 @@ public class NewTabPageView extends FrameLayout
// The page contents are initially hidden; otherwise they'll be drawn centered on the
// page before the most visited sites are available and then jump upwards to make space
// once the most visited sites are available.
- mContentView.setVisibility(View.VISIBLE);
+ mNewTabPageLayout.setVisibility(View.VISIBLE);
}
mSnapshotMostVisitedChanged = true;
}
@@ -1074,11 +1143,28 @@ public class NewTabPageView extends FrameLayout
}
}
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // Set the parent scroll view port height in the layout.
+ if (mNewTabPageLayout != null) {
+ mNewTabPageLayout.setParentScrollViewportHeight(MeasureSpec.getSize(heightMeasureSpec));
May 2016/05/05 16:28:22 If we're doing this here, do we still need the mNe
mcwilliams 2016/05/05 17:39:47 No, removed
+ }
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
private int getVerticalScroll() {
- if (mUseCardsUi) {
+ if (USE_CARDS_UI) {
return mRecyclerView.computeVerticalScrollOffset();
} else {
return mScrollView.getScrollY();
}
}
+
+ /**
+ * Are snippets currently enabled.
+ * @return
+ */
+ public static boolean isUseCardsUiEnabled() {
+ return USE_CARDS_UI;
PEConn 2016/05/05 16:31:28 What if the NewTabPageView hasn't been initialized
mcwilliams 2016/05/05 17:39:47 Done.
+ }
}

Powered by Google App Engine
This is Rietveld 408576698