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

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 18f226211dbe2c2878f401e803e48ba427b37c26..939c2d38d5920012c76e1bffebc705787f1c40c4 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
@@ -27,7 +27,6 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnLayoutChangeListener;
import android.view.ViewGroup;
-import android.view.ViewGroup.MarginLayoutParams;
import android.view.ViewStub;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -46,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;
@@ -84,7 +84,7 @@ public class NewTabPageView extends FrameLayout
private NewTabPageScrollView mScrollView;
private NewTabPageRecyclerView mRecyclerView;
- private NewTabPageLayout mContentView;
+ private NewTabPageLayout mNewTabPageLayout;
private LogoView mSearchProviderLogoView;
private View mSearchBoxView;
private ImageView mVoiceSearchButton;
@@ -93,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;
@@ -120,6 +120,8 @@ public class NewTabPageView extends FrameLayout
private int mSnapshotHeight;
private int mSnapshotScrollY;
+ private int mPeekingCardVerticalScrollStart;
+
/**
* Manages the view interaction with the rest of the system.
*/
@@ -278,28 +280,31 @@ public class NewTabPageView extends FrameLayout
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);
+ mNewTabPageLayout.setUseCardsUiEnabled(mUseCardsUi);
// 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);
@@ -333,7 +338,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) {
@@ -382,11 +387,12 @@ public class NewTabPageView extends FrameLayout
// Set up snippets
if (mUseCardsUi) {
- mNtpAdapter = new NewTabPageAdapter(mManager, mContentView);
- mRecyclerView.setAdapter(mNtpAdapter);
+ mNewTabPageAdapter = new NewTabPageAdapter(mManager, mNewTabPageLayout);
+ mRecyclerView.setAdapter(mNewTabPageAdapter);
// 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);
@@ -403,6 +409,7 @@ public class NewTabPageView extends FrameLayout
});
initializeSearchBoxRecyclerViewScrollHandling();
mRecyclerView.addItemDecoration(new SnippetItemDecoration());
+ updatePeekingCard();
} else {
initializeSearchBoxScrollHandling();
}
@@ -437,6 +444,52 @@ public class NewTabPageView extends FrameLayout
return mUseCardsUi ? mRecyclerView : mScrollView;
}
+ /**
+ * Calculate the peeking card/first snippet bleed and padding when scrolling if it is visible.
+ */
+ private void updatePeekingCard() {
+ // Get the first snippet that could display to make the peeking card transition.
+ View firstSnippetView = null;
+ int adapterSize = mNewTabPageAdapter.getItemCount();
+ for (int i = 0; i < adapterSize; 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 = getResources().getDimensionPixelSize(
+ R.dimen.snippets_padding_and_peeking_card_height);
+
+ // As the user scrolls, the bleed increases or decreases.
+ int bleed = maxPadding - (getVerticalScroll() - mPeekingCardVerticalScrollStart);
+
+ // 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. Top and bottom remain the same.
+ firstSnippetView.setPadding(
+ maxPadding - bleed, maxPadding, maxPadding - bleed, maxPadding);
+
+ // 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
+ * the RecyclerView.
+ */
private void initializeSearchBoxRecyclerViewScrollHandling() {
final Runnable mSnapScrollRunnable = new Runnable() {
@Override
@@ -447,13 +500,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.
@@ -466,17 +520,21 @@ public class NewTabPageView extends FrameLayout
mRecyclerView.getHeight() < mMostVisitedLayout.getBottom();
int targetScroll;
- if (currentScroll < mContentView.getHeight() / 3) {
+ // Set peeking card vertical scroll to be vertical scroll.
+ mPeekingCardVerticalScrollStart = 0;
+ 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) {
// If in the middle 1/3 and we are snapping to Most Likely, snap to it.
targetScroll = topOfMostLikelyScroll;
+ // Set the peeking card vertical scroll start for the snapped view.
+ mPeekingCardVerticalScrollStart = targetScroll;
} else {
// Otherwise, snap to the Articles.
targetScroll = topOfSnippetsScroll;
}
-
mRecyclerView.smoothScrollBy(0, targetScroll - currentScroll);
mPendingSnapScroll = false;
}
@@ -490,6 +548,7 @@ public class NewTabPageView extends FrameLayout
mRecyclerView.postDelayed(mSnapScrollRunnable, SNAP_SCROLL_DELAY_MS);
}
updateSearchBoxOnScroll();
+ updatePeekingCard();
}
});
@@ -511,13 +570,17 @@ public class NewTabPageView extends FrameLayout
});
}
+ /**
+ * Sets up scrolling when snippets are disabled. It adds scroll and touch listeners to the
+ * scroll 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);
}
@@ -601,9 +664,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;
@@ -686,11 +749,15 @@ public class NewTabPageView extends FrameLayout
// 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()));
+ 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 =
@@ -891,7 +958,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;
}
@@ -1072,6 +1139,15 @@ 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));
+ }
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
private int getVerticalScroll() {
if (mUseCardsUi) {
return mRecyclerView.computeVerticalScrollOffset();

Powered by Google App Engine
This is Rietveld 408576698