Commit 8bee090a authored by Angel Alvarez's avatar Angel Alvarez Committed by Commit Bot

Added new tile views for densified explore sites pages.

This involves the following changes:

1) Adding new dimensions in the XML to meet the spec for the explore sites
page.

2) Adding new tile views using new dimensions.

3) setting the tile view to use in CategoryCardViewHolderFactory.

4) Adjustments to the code for RoundedIconGenerator and
RoundedBitmapDrawable so that the icon size and radius are
programmatically adjusted.

5) Removal of an extra resize in ExploreSitesTileView which cause icons
to scale too many times creating resizing artifacts for both dense and
regular views. The RoundedBitmapDrawable already handles density based
resizing.

These changes form the bulk of the explore sites densification view
changes. What is left will be tweaks to padding on the category cards
and changes in tile quantity rendering logic.

Moved new dense feature params to a custom CondensedVariation, to be
wrapped under the condensed feature param in ExploreSitesVariation.
Added new supporting enums and utilities to allow access to condensed
variation from ExploreSitesBridge.

Bug: 977713
Change-Id: I795372339ea6350da6767aa613c55aeb2383bbaa
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1681955Reviewed-by: default avatarJustin DeWitt <dewittj@chromium.org>
Reviewed-by: default avatarTheresa <twellington@chromium.org>
Reviewed-by: default avatarCathy Li <chili@chromium.org>
Commit-Queue: Angel Alvarez <angelii@google.com>
Cr-Commit-Position: refs/heads/master@{#675783}
parent 2ea88cb7
<?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. -->
<org.chromium.chrome.browser.explore_sites.ExploreSitesTileView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="@dimen/explore_sites_dense_title_bottom_tile_view_width"
android:layout_height="@dimen/explore_sites_dense_title_bottom_tile_view_height"
app:iconCornerRadius="@dimen/explore_sites_dense_icon_corner_radius">
<!-- The icon background. -->
<View
android:id="@+id/tile_view_icon_background"
android:layout_width="@dimen/explore_sites_dense_icon_size"
android:layout_height="@dimen/explore_sites_dense_icon_size"
android:layout_marginTop="@dimen/explore_sites_dense_title_bottom_icon_margin_top"
android:layout_gravity="center_horizontal"
android:visibility="gone" />
<!-- The main icon. -->
<ImageView
android:id="@+id/tile_view_icon"
android:layout_width="@dimen/explore_sites_dense_icon_size"
android:layout_height="@dimen/explore_sites_dense_icon_size"
android:layout_marginTop="@dimen/explore_sites_dense_title_bottom_icon_margin_top"
android:layout_gravity="center_horizontal"
tools:ignore="ContentDescription" />
<!-- The touch highlight. -->
<View
android:id="@+id/tile_view_highlight"
android:background="@drawable/tile_view_highlight"
android:layout_width="@dimen/explore_sites_dense_icon_size"
android:layout_height="@dimen/explore_sites_dense_icon_size"
android:layout_marginTop="@dimen/explore_sites_dense_title_bottom_icon_margin_top"
android:layout_gravity="center_horizontal" />
<!-- The offline badge. -->
<ImageView
android:id="@+id/offline_badge"
android:layout_width="@dimen/tile_view_offline_badge_size_modern"
android:layout_height="@dimen/tile_view_offline_badge_size_modern"
android:layout_gravity="top|end"
android:layout_marginTop="0dp"
android:layout_marginEnd="@dimen/tile_view_offline_badge_margin_end_modern"
android:visibility="gone"
android:contentDescription="@string/accessibility_ntp_offline_badge"
app:srcCompat="@drawable/ic_offline_pin_blue_white" />
<org.chromium.ui.widget.TextViewWithLeading
android:id="@+id/tile_view_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/explore_sites_dense_title_bottom_title_margin_start"
android:ellipsize="end"
android:gravity="center_horizontal"
android:lines="2"
android:textAppearance="@style/TextAppearance.BlackCaption"
app:leading="@dimen/text_size_small_leading" />
</org.chromium.chrome.browser.explore_sites.ExploreSitesTileView>
\ No newline at end of file
<?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. -->
<org.chromium.chrome.browser.explore_sites.ExploreSitesTileView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="@dimen/explore_sites_dense_title_right_tile_view_width"
android:layout_height="@dimen/explore_sites_dense_title_right_tile_view_height"
android:orientation="horizontal">
<!-- The icon background. -->
<View
android:id="@+id/tile_view_icon_background"
android:layout_width="@dimen/explore_sites_dense_icon_size"
android:layout_height="@dimen/explore_sites_dense_icon_size"
android:layout_marginTop="@dimen/explore_sites_dense_title_bottom_icon_margin_top"
android:layout_gravity="center_horizontal"
android:visibility="gone" />
<!-- The main icon. -->
<ImageView
android:id="@+id/tile_view_icon"
android:layout_width="@dimen/explore_sites_dense_icon_size"
android:layout_height="@dimen/explore_sites_dense_icon_size"
android:layout_marginStart="@dimen/explore_sites_dense_title_right_icon_margin_start"
android:layout_gravity="center_vertical"
tools:ignore="ContentDescription" />
<!-- The touch highlight. -->
<View
android:id="@+id/tile_view_highlight"
android:background="@drawable/tile_view_highlight"
android:layout_width="@dimen/explore_sites_dense_icon_size"
android:layout_height="@dimen/explore_sites_dense_icon_size"
android:layout_marginStart="@dimen/explore_sites_dense_title_right_icon_margin_start"
android:layout_gravity="center_vertical" />
<!-- The offline badge. -->
<ImageView
android:id="@+id/offline_badge"
android:layout_width="@dimen/tile_view_offline_badge_size_modern"
android:layout_height="@dimen/tile_view_offline_badge_size_modern"
android:layout_marginTop="0dp"
android:layout_marginStart="@dimen/explore_sites_dense_offline_badge_margin_start"
android:visibility="gone"
android:contentDescription="@string/accessibility_ntp_offline_badge"
app:srcCompat="@drawable/ic_offline_pin_blue_white" />
<org.chromium.ui.widget.TextViewWithLeading
android:id="@+id/tile_view_title"
android:layout_width="match_parent"
android:layout_height="@dimen/explore_sites_dense_title_right_title_height"
android:layout_marginTop="@dimen/explore_sites_dense_title_right_title_margin_top"
android:layout_marginStart="@dimen/explore_sites_dense_title_right_title_margin_start"
android:ellipsize="end"
android:gravity="center_vertical"
android:lines="2"
android:textAppearance="@style/TextAppearance.BlackCaption"
app:leading="@dimen/text_size_small_leading" />
</org.chromium.chrome.browser.explore_sites.ExploreSitesTileView>
...@@ -88,4 +88,8 @@ ...@@ -88,4 +88,8 @@
<declare-styleable name="TileGridLayout"> <declare-styleable name="TileGridLayout">
<attr name="minHorizontalSpacing" format="dimension"/> <attr name="minHorizontalSpacing" format="dimension"/>
</declare-styleable> </declare-styleable>
<declare-styleable name="ExploreSitesTileView">
<attr name="iconCornerRadius" format="dimension"/>
</declare-styleable>
</resources> </resources>
...@@ -379,6 +379,23 @@ ...@@ -379,6 +379,23 @@
<dimen name="explore_sites_loading_spinny_size">36dp</dimen> <dimen name="explore_sites_loading_spinny_size">36dp</dimen>
<dimen name="explore_sites_loading_spinny_padding">24dp</dimen> <dimen name="explore_sites_loading_spinny_padding">24dp</dimen>
<dimen name="explore_sites_dense_icon_corner_radius">4dp</dimen>
<dimen name="explore_sites_dense_icon_size">32dp</dimen>
<dimen name="explore_sites_dense_icon_text_size">16dp</dimen>
<dimen name="explore_sites_dense_offline_badge_margin_start">26dp</dimen>
<dimen name="explore_sites_dense_title_right_icon_margin_start">4dp</dimen>
<dimen name="explore_sites_dense_title_right_tile_view_width">104dp</dimen>
<dimen name="explore_sites_dense_title_right_tile_view_height">40dp</dimen>
<dimen name="explore_sites_dense_title_right_title_height">32dp</dimen>
<dimen name="explore_sites_dense_title_right_title_margin_start">40dp</dimen>
<dimen name="explore_sites_dense_title_right_title_margin_top">4dp</dimen>
<dimen name="explore_sites_dense_title_bottom_icon_margin_top">4dp</dimen>
<dimen name="explore_sites_dense_title_bottom_tile_view_height">72dp</dimen>
<dimen name="explore_sites_dense_title_bottom_tile_view_width">64dp</dimen>
<dimen name="explore_sites_dense_title_bottom_title_margin_start">40dp</dimen>
<!-- Recent tabs page --> <!-- Recent tabs page -->
<dimen name="recent_tabs_visible_separator_padding">8dp</dimen> <dimen name="recent_tabs_visible_separator_padding">8dp</dimen>
<dimen name="recent_tabs_group_view_vertical_padding">8dp</dimen> <dimen name="recent_tabs_group_view_vertical_padding">8dp</dimen>
......
...@@ -15,6 +15,24 @@ import org.chromium.ui.modelutil.RecyclerViewAdapter; ...@@ -15,6 +15,24 @@ import org.chromium.ui.modelutil.RecyclerViewAdapter;
/** Factory to create CategoryCardViewHolder objects. */ /** Factory to create CategoryCardViewHolder objects. */
public class CategoryCardViewHolderFactory implements RecyclerViewAdapter.ViewHolderFactory< public class CategoryCardViewHolderFactory implements RecyclerViewAdapter.ViewHolderFactory<
CategoryCardViewHolderFactory.CategoryCardViewHolder> { CategoryCardViewHolderFactory.CategoryCardViewHolder> {
private int mTileViewResource;
CategoryCardViewHolderFactory() {
final int exploreSitesDenseVariation = ExploreSitesBridge.getDenseVariation();
// Set the tile view to use based on the condensed variation.
if (ExploreSitesBridge.isDense(exploreSitesDenseVariation)) {
if (exploreSitesDenseVariation == DenseVariation.DENSE_TITLE_BOTTOM) {
mTileViewResource = R.layout.explore_sites_dense_tile_bottom_view;
} else if (exploreSitesDenseVariation == DenseVariation.DENSE_TITLE_RIGHT) {
mTileViewResource = R.layout.explore_sites_dense_tile_right_view;
} else {
mTileViewResource = R.layout.explore_sites_tile_view;
}
} else {
mTileViewResource = R.layout.explore_sites_tile_view;
}
}
/** View holder for the recycler view. */ /** View holder for the recycler view. */
public static class CategoryCardViewHolder extends RecyclerView.ViewHolder { public static class CategoryCardViewHolder extends RecyclerView.ViewHolder {
public CategoryCardViewHolder(View view) { public CategoryCardViewHolder(View view) {
...@@ -32,7 +50,7 @@ public class CategoryCardViewHolderFactory implements RecyclerViewAdapter.ViewHo ...@@ -32,7 +50,7 @@ public class CategoryCardViewHolderFactory implements RecyclerViewAdapter.ViewHo
* cards. * cards.
*/ */
protected int getTileViewResource() { protected int getTileViewResource() {
return R.layout.explore_sites_tile_view; return mTileViewResource;
} }
@Override @Override
......
...@@ -135,12 +135,27 @@ public class ExploreSitesPage extends BasicNativePage { ...@@ -135,12 +135,27 @@ public class ExploreSitesPage extends BasicNativePage {
Context context = mView.getContext(); Context context = mView.getContext();
mLayoutManager = new StableScrollLayoutManager(context); mLayoutManager = new StableScrollLayoutManager(context);
int iconSizePx = context.getResources().getDimensionPixelSize(R.dimen.tile_view_icon_size); int iconSizePx;
RoundedIconGenerator iconGenerator = new RoundedIconGenerator(iconSizePx, iconSizePx, int textSizeDimensionResource;
iconSizePx / 2, int iconRadius;
ApiCompatibilityUtils.getColor( boolean isDense = ExploreSitesBridge.isDense(ExploreSitesBridge.getDenseVariation());
context.getResources(), R.color.default_favicon_background_color), if (isDense) {
context.getResources().getDimensionPixelSize(R.dimen.tile_view_icon_text_size)); iconSizePx = context.getResources().getDimensionPixelSize(
R.dimen.explore_sites_dense_icon_size);
iconRadius = context.getResources().getDimensionPixelSize(
R.dimen.explore_sites_dense_icon_corner_radius);
textSizeDimensionResource = R.dimen.explore_sites_dense_icon_text_size;
} else {
iconSizePx = context.getResources().getDimensionPixelSize(R.dimen.tile_view_icon_size);
textSizeDimensionResource = R.dimen.tile_view_icon_text_size;
iconRadius = iconSizePx / 2;
}
RoundedIconGenerator iconGenerator =
new RoundedIconGenerator(iconSizePx, iconSizePx, iconRadius,
ApiCompatibilityUtils.getColor(
context.getResources(), R.color.default_favicon_background_color),
context.getResources().getDimensionPixelSize(textSizeDimensionResource));
NativePageNavigationDelegateImpl navDelegate = new NativePageNavigationDelegateImpl( NativePageNavigationDelegateImpl navDelegate = new NativePageNavigationDelegateImpl(
activity, mProfile, host, activity.getTabModelSelector()); activity, mProfile, host, activity.getTabModelSelector());
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package org.chromium.chrome.browser.explore_sites; package org.chromium.chrome.browser.explore_sites;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
...@@ -20,15 +21,18 @@ import org.chromium.chrome.browser.widget.tile.TileWithTextView; ...@@ -20,15 +21,18 @@ import org.chromium.chrome.browser.widget.tile.TileWithTextView;
*/ */
public class ExploreSitesTileView extends TileWithTextView { public class ExploreSitesTileView extends TileWithTextView {
private static final int TITLE_LINES = 2; private static final int TITLE_LINES = 2;
private final int mIconCornerRadius;
private final int mIconSizePx;
// Used to generate textual icons. // Used to generate textual icons.
private RoundedIconGenerator mIconGenerator; private RoundedIconGenerator mIconGenerator;
public ExploreSitesTileView(Context ctx, AttributeSet attrs) { public ExploreSitesTileView(Context ctx, AttributeSet attrs) {
super(ctx, attrs); super(ctx, attrs);
mIconSizePx = getResources().getDimensionPixelSize(R.dimen.tile_view_icon_size); TypedArray styleAttrs = ctx.obtainStyledAttributes(attrs, R.styleable.ExploreSitesTileView);
mIconCornerRadius =
styleAttrs.getDimensionPixelSize(R.styleable.ExploreSitesTileView_iconCornerRadius,
ViewUtils.DEFAULT_FAVICON_CORNER_RADIUS);
styleAttrs.recycle();
} }
public void initialize(RoundedIconGenerator generator) { public void initialize(RoundedIconGenerator generator) {
...@@ -47,8 +51,6 @@ public class ExploreSitesTileView extends TileWithTextView { ...@@ -47,8 +51,6 @@ public class ExploreSitesTileView extends TileWithTextView {
if (image == null) { if (image == null) {
return new BitmapDrawable(getResources(), mIconGenerator.generateIconForText(text)); return new BitmapDrawable(getResources(), mIconGenerator.generateIconForText(text));
} }
return ViewUtils.createRoundedBitmapDrawable( return ViewUtils.createRoundedBitmapDrawable(image, mIconCornerRadius);
Bitmap.createScaledBitmap(image, mIconSizePx, mIconSizePx, false),
ViewUtils.DEFAULT_FAVICON_CORNER_RADIUS);
} }
} }
...@@ -53,7 +53,6 @@ import java.util.ArrayList; ...@@ -53,7 +53,6 @@ import java.util.ArrayList;
// clang-format off // clang-format off
@RunWith(ChromeJUnit4ClassRunner.class) @RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
@Features.EnableFeatures(ChromeFeatureList.EXPLORE_SITES)
public class ExploreSitesPageTest { public class ExploreSitesPageTest {
// clang-format on // clang-format on
...@@ -116,6 +115,7 @@ public class ExploreSitesPageTest { ...@@ -116,6 +115,7 @@ public class ExploreSitesPageTest {
@SmallTest @SmallTest
@DisabledTest @DisabledTest
@Feature({"ExploreSites", "RenderTest"}) @Feature({"ExploreSites", "RenderTest"})
@Features.EnableFeatures(ChromeFeatureList.EXPLORE_SITES)
public void testScrolledLayout_withBack() throws Exception { public void testScrolledLayout_withBack() throws Exception {
final int scrollPosition = 2; final int scrollPosition = 2;
onView(instanceOf(RecyclerView.class)) onView(instanceOf(RecyclerView.class))
...@@ -135,6 +135,7 @@ public class ExploreSitesPageTest { ...@@ -135,6 +135,7 @@ public class ExploreSitesPageTest {
@Test @Test
@SmallTest @SmallTest
@Feature({"ExploreSites", "RenderTest"}) @Feature({"ExploreSites", "RenderTest"})
@Features.EnableFeatures(ChromeFeatureList.EXPLORE_SITES)
public void testInitialLayout() throws Exception { public void testInitialLayout() throws Exception {
onView(instanceOf(RecyclerView.class)).perform(RecyclerViewActions.scrollToPosition(0)); onView(instanceOf(RecyclerView.class)).perform(RecyclerViewActions.scrollToPosition(0));
mRenderTestRule.render(mRecyclerView, "initial_layout"); mRenderTestRule.render(mRecyclerView, "initial_layout");
...@@ -143,7 +144,7 @@ public class ExploreSitesPageTest { ...@@ -143,7 +144,7 @@ public class ExploreSitesPageTest {
@Test @Test
@SmallTest @SmallTest
@CommandLineFlags. @CommandLineFlags.
Add({"enabled-features=ExploreSites<FakeStudyName", "force-fieldtrials=FakeStudyName/Enabled", Add({"enable-features=ExploreSites<FakeStudyName", "force-fieldtrials=FakeStudyName/Enabled",
"force-fieldtrial-params=FakeStudyName.Enabled:variation/mostLikelyTile"}) "force-fieldtrial-params=FakeStudyName.Enabled:variation/mostLikelyTile"})
@Feature({"ExploreSites", "RenderTest"}) @Feature({"ExploreSites", "RenderTest"})
public void public void
...@@ -152,9 +153,40 @@ public class ExploreSitesPageTest { ...@@ -152,9 +153,40 @@ public class ExploreSitesPageTest {
Assert.assertEquals(0, getFirstVisiblePosition()); Assert.assertEquals(0, getFirstVisiblePosition());
} }
@Test
@SmallTest
@CommandLineFlags.
Add({"enable-features=ExploreSites<FakeStudyName", "force-fieldtrials=FakeStudyName/Enabled",
"force-fieldtrial-params=FakeStudyName.Enabled:variation/mostLikelyTile"
+ "/denseVariation/titleBottom"})
@Feature({"ExploreSites"})
public void
testInitialLayout_DenseTitleBottom() throws Exception {
// Ensure that the DenseTitleBottomView has loaded without crashing
Assert.assertEquals(
DenseVariation.DENSE_TITLE_BOTTOM, ExploreSitesBridge.getDenseVariation());
// TODO(angelii): Add render test once layout is finalized.
}
@Test
@SmallTest
@CommandLineFlags.
Add({"enable-features=ExploreSites<FakeStudyName", "force-fieldtrials=FakeStudyName/Enabled",
"force-fieldtrial-params=FakeStudyName.Enabled:variation/mostLikelyTile"
+ "/denseVariation/titleRight"})
@Feature({"ExploreSites"})
public void
testInitialLayout_DenseTitleRight() throws Exception {
// Ensure that the DenseTitleRightView has loaded without crashing
Assert.assertEquals(
DenseVariation.DENSE_TITLE_RIGHT, ExploreSitesBridge.getDenseVariation());
// TODO(angelii): Add render test once layout is finalized.
}
@Test @Test
@SmallTest @SmallTest
@Feature({"ExploreSites", "RenderTest"}) @Feature({"ExploreSites", "RenderTest"})
@Features.EnableFeatures(ChromeFeatureList.EXPLORE_SITES)
public void testScrollingFromNTP() throws Exception { public void testScrollingFromNTP() throws Exception {
mActivityTestRule.loadUrl("about:blank"); mActivityTestRule.loadUrl("about:blank");
ExploreSitesCategory category = getTestingCatalog().get(2); ExploreSitesCategory category = getTestingCatalog().get(2);
...@@ -172,6 +204,7 @@ public class ExploreSitesPageTest { ...@@ -172,6 +204,7 @@ public class ExploreSitesPageTest {
@Test @Test
@SmallTest @SmallTest
@Feature({"ExploreSites", "RenderTest"}) @Feature({"ExploreSites", "RenderTest"})
@Features.EnableFeatures(ChromeFeatureList.EXPLORE_SITES)
public void testFocusRetention_WithBack() throws Exception { public void testFocusRetention_WithBack() throws Exception {
Assume.assumeTrue(FeatureUtilities.isNoTouchModeEnabled()); Assume.assumeTrue(FeatureUtilities.isNoTouchModeEnabled());
......
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