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 @@
<declare-styleable name="TileGridLayout">
<attr name="minHorizontalSpacing" format="dimension"/>
</declare-styleable>
<declare-styleable name="ExploreSitesTileView">
<attr name="iconCornerRadius" format="dimension"/>
</declare-styleable>
</resources>
......@@ -379,6 +379,23 @@
<dimen name="explore_sites_loading_spinny_size">36dp</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 -->
<dimen name="recent_tabs_visible_separator_padding">8dp</dimen>
<dimen name="recent_tabs_group_view_vertical_padding">8dp</dimen>
......
......@@ -15,6 +15,24 @@ import org.chromium.ui.modelutil.RecyclerViewAdapter;
/** Factory to create CategoryCardViewHolder objects. */
public class CategoryCardViewHolderFactory implements RecyclerViewAdapter.ViewHolderFactory<
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. */
public static class CategoryCardViewHolder extends RecyclerView.ViewHolder {
public CategoryCardViewHolder(View view) {
......@@ -32,7 +50,7 @@ public class CategoryCardViewHolderFactory implements RecyclerViewAdapter.ViewHo
* cards.
*/
protected int getTileViewResource() {
return R.layout.explore_sites_tile_view;
return mTileViewResource;
}
@Override
......
......@@ -135,12 +135,27 @@ public class ExploreSitesPage extends BasicNativePage {
Context context = mView.getContext();
mLayoutManager = new StableScrollLayoutManager(context);
int iconSizePx = context.getResources().getDimensionPixelSize(R.dimen.tile_view_icon_size);
RoundedIconGenerator iconGenerator = new RoundedIconGenerator(iconSizePx, iconSizePx,
iconSizePx / 2,
ApiCompatibilityUtils.getColor(
context.getResources(), R.color.default_favicon_background_color),
context.getResources().getDimensionPixelSize(R.dimen.tile_view_icon_text_size));
int iconSizePx;
int textSizeDimensionResource;
int iconRadius;
boolean isDense = ExploreSitesBridge.isDense(ExploreSitesBridge.getDenseVariation());
if (isDense) {
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(
activity, mProfile, host, activity.getTabModelSelector());
......
......@@ -5,6 +5,7 @@
package org.chromium.chrome.browser.explore_sites;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
......@@ -20,15 +21,18 @@ import org.chromium.chrome.browser.widget.tile.TileWithTextView;
*/
public class ExploreSitesTileView extends TileWithTextView {
private static final int TITLE_LINES = 2;
private final int mIconSizePx;
private final int mIconCornerRadius;
// Used to generate textual icons.
private RoundedIconGenerator mIconGenerator;
public ExploreSitesTileView(Context ctx, AttributeSet 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) {
......@@ -47,8 +51,6 @@ public class ExploreSitesTileView extends TileWithTextView {
if (image == null) {
return new BitmapDrawable(getResources(), mIconGenerator.generateIconForText(text));
}
return ViewUtils.createRoundedBitmapDrawable(
Bitmap.createScaledBitmap(image, mIconSizePx, mIconSizePx, false),
ViewUtils.DEFAULT_FAVICON_CORNER_RADIUS);
return ViewUtils.createRoundedBitmapDrawable(image, mIconCornerRadius);
}
}
......@@ -53,7 +53,6 @@ import java.util.ArrayList;
// clang-format off
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
@Features.EnableFeatures(ChromeFeatureList.EXPLORE_SITES)
public class ExploreSitesPageTest {
// clang-format on
......@@ -116,6 +115,7 @@ public class ExploreSitesPageTest {
@SmallTest
@DisabledTest
@Feature({"ExploreSites", "RenderTest"})
@Features.EnableFeatures(ChromeFeatureList.EXPLORE_SITES)
public void testScrolledLayout_withBack() throws Exception {
final int scrollPosition = 2;
onView(instanceOf(RecyclerView.class))
......@@ -135,6 +135,7 @@ public class ExploreSitesPageTest {
@Test
@SmallTest
@Feature({"ExploreSites", "RenderTest"})
@Features.EnableFeatures(ChromeFeatureList.EXPLORE_SITES)
public void testInitialLayout() throws Exception {
onView(instanceOf(RecyclerView.class)).perform(RecyclerViewActions.scrollToPosition(0));
mRenderTestRule.render(mRecyclerView, "initial_layout");
......@@ -143,7 +144,7 @@ public class ExploreSitesPageTest {
@Test
@SmallTest
@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"})
@Feature({"ExploreSites", "RenderTest"})
public void
......@@ -152,9 +153,40 @@ public class ExploreSitesPageTest {
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
@SmallTest
@Feature({"ExploreSites", "RenderTest"})
@Features.EnableFeatures(ChromeFeatureList.EXPLORE_SITES)
public void testScrollingFromNTP() throws Exception {
mActivityTestRule.loadUrl("about:blank");
ExploreSitesCategory category = getTestingCatalog().get(2);
......@@ -172,6 +204,7 @@ public class ExploreSitesPageTest {
@Test
@SmallTest
@Feature({"ExploreSites", "RenderTest"})
@Features.EnableFeatures(ChromeFeatureList.EXPLORE_SITES)
public void testFocusRetention_WithBack() throws Exception {
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