| Index: chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
|
| index b54dee74d8921d6f19d98452de98563b29956655..90d0e4314ec18b5855e74e7a17b83dc006872e2e 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
|
| @@ -6,7 +6,6 @@ package org.chromium.chrome.browser.ntp;
|
|
|
| import android.content.Context;
|
| import android.content.res.Resources;
|
| -import android.support.v7.widget.RecyclerView;
|
| import android.util.AttributeSet;
|
| import android.view.View;
|
| import android.widget.LinearLayout;
|
| @@ -27,18 +26,23 @@ public class NewTabPageLayout extends LinearLayout {
|
| private static final float TOTAL_SPACER_HEIGHT_DP = TOP_SPACER_HEIGHT_DP
|
| + MIDDLE_SPACER_HEIGHT_DP + BOTTOM_SPACER_HEIGHT_DP;
|
|
|
| - private final int mTopSpacerHeight;
|
| - private final int mMiddleSpacerHeight;
|
| - private final int mBottomSpacerHeight;
|
| - private final int mTotalSpacerHeight;
|
| + private final int mTopSpacerIdealHeight;
|
| + private final int mMiddleSpacerIdealHeight;
|
| + private final int mBottomSpacerIdealHeight;
|
| + private final int mTotalSpacerIdealHeight;
|
| private final int mMostVisitedLayoutBleed;
|
| + private final int mPeekingCardHeight;
|
| + private final int mTabStripHeight;
|
|
|
| - private int mParentScrollViewportHeight;
|
| + private int mParentViewportHeight;
|
|
|
| private boolean mCardsUiEnabled;
|
| - private View mTopSpacer;
|
| - private View mMiddleSpacer;
|
| - private View mBottomSpacer;
|
| + private View mTopSpacer; // Spacer above search logo.
|
| + private View mMiddleSpacer; // Spacer between toolbar and Most Likely.
|
| + private View mBottomSpacer; // Spacer below Most Likely.
|
| +
|
| + // Separate spacer below Most Likely to add enough space so the user can scroll with Most Likely
|
| + // at the top of the screen.
|
| private View mScrollCompensationSpacer;
|
|
|
| private LogoView mSearchProviderLogoView;
|
| @@ -52,11 +56,15 @@ public class NewTabPageLayout extends LinearLayout {
|
| super(context, attrs);
|
| Resources res = getResources();
|
| float density = res.getDisplayMetrics().density;
|
| - mTopSpacerHeight = Math.round(density * TOP_SPACER_HEIGHT_DP);
|
| - mMiddleSpacerHeight = Math.round(density * MIDDLE_SPACER_HEIGHT_DP);
|
| - mBottomSpacerHeight = Math.round(density * BOTTOM_SPACER_HEIGHT_DP);
|
| - mTotalSpacerHeight = Math.round(density * TOTAL_SPACER_HEIGHT_DP);
|
| + mTopSpacerIdealHeight = Math.round(density * TOP_SPACER_HEIGHT_DP);
|
| + mMiddleSpacerIdealHeight = Math.round(density * MIDDLE_SPACER_HEIGHT_DP);
|
| + mBottomSpacerIdealHeight = Math.round(density * BOTTOM_SPACER_HEIGHT_DP);
|
| + mTotalSpacerIdealHeight = Math.round(density * TOTAL_SPACER_HEIGHT_DP);
|
| mMostVisitedLayoutBleed = res.getDimensionPixelSize(R.dimen.most_visited_layout_bleed);
|
| +
|
| + mPeekingCardHeight = getResources()
|
| + .getDimensionPixelSize(R.dimen.snippets_padding_and_peeking_card_height);
|
| + mTabStripHeight = getResources().getDimensionPixelSize(R.dimen.tab_strip_height);
|
| }
|
|
|
| @Override
|
| @@ -72,20 +80,20 @@ public class NewTabPageLayout extends LinearLayout {
|
| }
|
|
|
| /**
|
| - * Specifies the height of the scroll viewport for the container view of this View.
|
| + * Specifies the height of the parent's viewport for the container view of this View.
|
| *
|
| - * <p>
|
| * As this is required in onMeasure, we can not rely on the parent having the proper
|
| * size set yet and thus must be told explicitly of this size.
|
| *
|
| - * @param height The height of the scroll viewport containing this view.
|
| + * This View takes into account the presence of the tab strip height for tablets.
|
| */
|
| - public void setParentScrollViewportHeight(int height) {
|
| - mParentScrollViewportHeight = height;
|
| + public void setParentViewportHeight(int height) {
|
| + mParentViewportHeight = height;
|
| }
|
|
|
| /**
|
| * Sets whether the cards UI is enabled.
|
| + * This view assumes that a peeking card will always be present when the cards UI is used.
|
| */
|
| public void setUseCardsUiEnabled(boolean useCardsUi) {
|
| mCardsUiEnabled = useCardsUi;
|
| @@ -93,75 +101,71 @@ public class NewTabPageLayout extends LinearLayout {
|
|
|
| @Override
|
| protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
| - mScrollCompensationSpacer.getLayoutParams().height = 0;
|
| + mScrollCompensationSpacer.setVisibility(View.GONE);
|
| super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
|
| - // Check if we are showing snippets. If Most Likely is fully rendered on the initial page
|
| - // load and has enough space for the peeking card, push snippets to the bottom of the page
|
| - // to show the peeking card.
|
| - if (mCardsUiEnabled) {
|
| - int peekingCardHeight = getResources().getDimensionPixelSize(
|
| - R.dimen.snippets_padding_and_peeking_card_height);
|
| + if (getMeasuredHeight() > mParentViewportHeight) {
|
| + // This layout is bigger than its parent's viewport, so the user will need to scroll
|
| + // to see all of it. Extra spacing should be added at the bottom so the user can scroll
|
| + // until Most Visited is at the top.
|
|
|
| - // Height of the tabs for tablet. This will be zero for mobile.
|
| - int tabStripHeight = getResources().getDimensionPixelSize(R.dimen.tab_strip_height);
|
| -
|
| - if (mParentScrollViewportHeight
|
| - >= getMeasuredHeight() + peekingCardHeight + tabStripHeight) {
|
| - RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) getLayoutParams();
|
| - params.height = mParentScrollViewportHeight - peekingCardHeight - tabStripHeight;
|
| - }
|
| - }
|
| - // TODO(https://crbug.com/609487): Push snippets below the fold when most likely
|
| - // is not fully rendered.
|
| + // All the spacers have height 0 since they use weights to set height.
|
| + assert mTopSpacer.getMeasuredHeight() == 0;
|
|
|
| - distributeExtraSpace(mTopSpacer.getMeasuredHeight());
|
| + final int topOfMostVisited = calculateTopOfMostVisited();
|
| + final int belowTheFoldHeight = getMeasuredHeight() - mParentViewportHeight;
|
| + if (belowTheFoldHeight < topOfMostVisited) {
|
| + mScrollCompensationSpacer.getLayoutParams().height =
|
| + topOfMostVisited - belowTheFoldHeight;
|
|
|
| - int minScrollAmountRequired = 0;
|
| - for (int i = 0; i < getChildCount(); i++) {
|
| - View child = getChildAt(i);
|
| + if (mCardsUiEnabled) {
|
| + // If we have a peeking card, allow that to show at the bottom of the screen.
|
| + mScrollCompensationSpacer.getLayoutParams().height -= mPeekingCardHeight;
|
| + }
|
|
|
| - MarginLayoutParams layoutParams = (MarginLayoutParams) child.getLayoutParams();
|
| - if (child.getVisibility() != View.GONE) {
|
| - minScrollAmountRequired += layoutParams.topMargin;
|
| + mScrollCompensationSpacer.setVisibility(View.INVISIBLE);
|
| + super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
| }
|
| -
|
| - if (child.getId() == R.id.most_visited_layout) break;
|
| -
|
| - if (child.getVisibility() != View.GONE) {
|
| - minScrollAmountRequired += child.getMeasuredHeight();
|
| - minScrollAmountRequired += layoutParams.bottomMargin;
|
| + } else {
|
| + // This layout is smaller than it's parent viewport, redistribute the extra space.
|
| + if (mCardsUiEnabled) {
|
| + getLayoutParams().height = Math.max(getMeasuredHeight(),
|
| + mParentViewportHeight - mPeekingCardHeight - mTabStripHeight);
|
| + // Call onMeasure to update mTopScaper's height.
|
| + super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
| }
|
| - }
|
| -
|
| - int scrollVsHeightDiff = getMeasuredHeight() - mParentScrollViewportHeight;
|
| - if (getMeasuredHeight() > mParentScrollViewportHeight
|
| - && scrollVsHeightDiff < minScrollAmountRequired) {
|
| - mScrollCompensationSpacer.getLayoutParams().height =
|
| - minScrollAmountRequired - scrollVsHeightDiff;
|
| - mScrollCompensationSpacer.setVisibility(View.INVISIBLE);
|
| -
|
| - super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
| distributeExtraSpace(mTopSpacer.getMeasuredHeight());
|
| - } else {
|
| - mScrollCompensationSpacer.setVisibility(View.GONE);
|
| }
|
|
|
| - // Make the search box and logo as wide as the most visited items
|
| + // Make the search box and logo as wide as the most visited items.
|
| if (mMostVisitedLayout.getVisibility() != GONE) {
|
| - int mostVisitedWidthSpec = MeasureSpec.makeMeasureSpec(
|
| - mMostVisitedLayout.getMeasuredWidth() - mMostVisitedLayoutBleed,
|
| - MeasureSpec.EXACTLY);
|
| - int searchBoxHeight = MeasureSpec.makeMeasureSpec(
|
| - mSearchBoxView.getMeasuredHeight(), MeasureSpec.EXACTLY);
|
| - mSearchBoxView.measure(mostVisitedWidthSpec, searchBoxHeight);
|
| - int logoHeight = MeasureSpec.makeMeasureSpec(
|
| - mSearchProviderLogoView.getMeasuredHeight(), MeasureSpec.EXACTLY);
|
| - mSearchProviderLogoView.measure(mostVisitedWidthSpec, logoHeight);
|
| + final int width = mMostVisitedLayout.getMeasuredWidth() - mMostVisitedLayoutBleed;
|
| + setMeasure(mSearchBoxView, width, mSearchBoxView.getMeasuredHeight());
|
| + setMeasure(mSearchProviderLogoView, width, mSearchProviderLogoView.getMeasuredHeight());
|
| }
|
| }
|
|
|
| /**
|
| + * Calculate the vertical position of Most Visited.
|
| + * This method does not use mMostVisitedLayout.getTop(), so can be called in onMeasure.
|
| + */
|
| + private int calculateTopOfMostVisited() {
|
| + // Manually add the heights (and margins) of all children above Most Visited.
|
| + int top = 0;
|
| + int mostVisitedIndex = indexOfChild(mMostVisitedLayout);
|
| + for (int i = 0; i < mostVisitedIndex; i++) {
|
| + View child = getChildAt(i);
|
| + MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();
|
| +
|
| + if (child.getVisibility() != View.GONE) {
|
| + top += params.topMargin + child.getMeasuredHeight() + params.bottomMargin;
|
| + }
|
| + }
|
| + top += ((MarginLayoutParams) mMostVisitedLayout.getLayoutParams()).topMargin;
|
| + return top;
|
| + }
|
| +
|
| + /**
|
| * Distribute extra vertical space between the three spacer views.
|
| * @param extraHeight The amount of extra space, in pixels.
|
| */
|
| @@ -170,31 +174,33 @@ public class NewTabPageLayout extends LinearLayout {
|
| int middleSpacerHeight;
|
| int bottomSpacerHeight;
|
|
|
| - if (extraHeight < mTotalSpacerHeight) {
|
| - topSpacerHeight = Math.round(extraHeight
|
| - * (TOP_SPACER_HEIGHT_DP / TOTAL_SPACER_HEIGHT_DP));
|
| - extraHeight -= topSpacerHeight;
|
| - middleSpacerHeight = Math.round(extraHeight * (MIDDLE_SPACER_HEIGHT_DP
|
| - / (MIDDLE_SPACER_HEIGHT_DP + BOTTOM_SPACER_HEIGHT_DP)));
|
| - extraHeight -= middleSpacerHeight;
|
| - bottomSpacerHeight = extraHeight;
|
| + if (extraHeight < mTotalSpacerIdealHeight) {
|
| + // The spacers will be less than their ideal height, shrink them proportionally.
|
| + topSpacerHeight =
|
| + Math.round(extraHeight * (TOP_SPACER_HEIGHT_DP / TOTAL_SPACER_HEIGHT_DP));
|
| + middleSpacerHeight =
|
| + Math.round(extraHeight * (MIDDLE_SPACER_HEIGHT_DP / TOTAL_SPACER_HEIGHT_DP));
|
| + bottomSpacerHeight = extraHeight - topSpacerHeight - middleSpacerHeight;
|
| } else {
|
| - topSpacerHeight = mTopSpacerHeight;
|
| - middleSpacerHeight = mMiddleSpacerHeight;
|
| - bottomSpacerHeight = mBottomSpacerHeight;
|
| - extraHeight -= mTotalSpacerHeight;
|
| -
|
| // Distribute remaining space evenly between the top and bottom spacers.
|
| - topSpacerHeight += (extraHeight + 1) / 2;
|
| - bottomSpacerHeight += extraHeight / 2;
|
| + extraHeight -= mTotalSpacerIdealHeight;
|
| + topSpacerHeight = mTopSpacerIdealHeight + extraHeight / 2;
|
| + middleSpacerHeight = mMiddleSpacerIdealHeight;
|
| + bottomSpacerHeight = mBottomSpacerIdealHeight + extraHeight / 2;
|
| }
|
|
|
| - int widthSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY);
|
| - mTopSpacer.measure(widthSpec,
|
| - MeasureSpec.makeMeasureSpec(topSpacerHeight, MeasureSpec.EXACTLY));
|
| - mMiddleSpacer.measure(widthSpec,
|
| - MeasureSpec.makeMeasureSpec(middleSpacerHeight, MeasureSpec.EXACTLY));
|
| - mBottomSpacer.measure(widthSpec,
|
| - MeasureSpec.makeMeasureSpec(bottomSpacerHeight, MeasureSpec.EXACTLY));
|
| + setMeasure(mTopSpacer, 0, topSpacerHeight);
|
| + setMeasure(mMiddleSpacer, 0, middleSpacerHeight);
|
| + setMeasure(mBottomSpacer, 0, bottomSpacerHeight);
|
| + }
|
| +
|
| +
|
| + /**
|
| + * Convenience method to call |measure| on the given View with MeasureSpecs converted from the
|
| + * given dimensions (in pixels) with MeasureSpec.EXACTLY.
|
| + */
|
| + private void setMeasure(View view, int widthPx, int heightPx) {
|
| + view.measure(MeasureSpec.makeMeasureSpec(widthPx, MeasureSpec.EXACTLY),
|
| + MeasureSpec.makeMeasureSpec(heightPx, MeasureSpec.EXACTLY));
|
| }
|
| }
|
|
|