Commit 310bb105 authored by Sinan Sahin's avatar Sinan Sahin Committed by Commit Bot

Progress on the Revamped context menu

This CL consists of:
- Improvements for URL formatting (i18n and emphasizing)
- Addition of grey background while loading
- Addition of favicons, monograms, and thumbnails
- Addition of checkered pattern behind the transparent PNGs
- Some visual polish and fixes

Bug: 655359
Change-Id: I6ebf13b6097780db22c05804f2b9cdf6d1ee8461
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1595114Reviewed-by: default avatarTheresa <twellington@chromium.org>
Commit-Queue: Sinan Sahin <sinansahin@google.com>
Cr-Commit-Position: refs/heads/master@{#659233}
parent e95d05c7
......@@ -7,25 +7,25 @@
<item>
<shape android:shape="rectangle">
<solid android:color="@android:color/white" />
<size android:height="10dp" android:width="10dp"/>
<size android:height="4dp" android:width="4dp"/>
</shape>
</item>
<item android:top="0dp" android:left="10dp">
<item android:top="0dp" android:left="4dp">
<shape android:shape="rectangle">
<solid android:color="@color/modern_grey_200"/>
<size android:height="10dp" android:width="10dp"/>
<size android:height="4dp" android:width="4dp"/>
</shape>
</item>
<item android:top="10dp" android:left="0dp">
<item android:top="4dp" android:left="0dp">
<shape android:shape="rectangle">
<solid android:color="@color/modern_grey_200"/>
<size android:height="10dp" android:width="10dp"/>
<size android:height="4dp" android:width="4dp"/>
</shape>
</item>
<item android:top="10dp" android:left="10dp">
<item android:top="4dp" android:left="4dp">
<shape android:shape="rectangle">
<solid android:color="@android:color/white" />
<size android:height="10dp" android:width="10dp"/>
<size android:height="4dp" android:width="4dp"/>
</shape>
</item>
</layer-list>
<?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. -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/revamped_context_menu_divider_padding">
<!-- TODO(sinansahin): divider_preference can be renamed to horizontal_divider -->
<include layout="@layout/divider_preference" />
</FrameLayout>
\ No newline at end of file
......@@ -13,7 +13,10 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="24dp"
android:layout_marginStart="@dimen/revamped_context_menu_lateral_margin"
android:layout_marginEnd="@dimen/revamped_context_menu_lateral_margin"
android:layout_marginTop="@dimen/revamped_context_menu_vertical_margin"
android:layout_marginBottom="@dimen/revamped_context_menu_vertical_margin"
android:background="@drawable/popup_bg_tinted"
android:divider="@null" />
</FrameLayout>
\ No newline at end of file
......@@ -5,46 +5,71 @@
<!-- We used nested LinearLayouts here because it was harder to align the text vertically with
the center of the image using a single RelativeLayout. A ConstraintLayout could be a better
choice here, but it isn't available to us, yet -->
choice here, but it isn't available to us, yet. -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:paddingStart="16dp"
android:paddingEnd="16dp" >
android:paddingStart="@dimen/revamped_context_menu_list_lateral_padding"
android:paddingEnd="@dimen/revamped_context_menu_list_lateral_padding"
android:paddingTop="@dimen/revamped_context_menu_header_vertical_padding"
android:paddingBottom="@dimen/revamped_context_menu_header_vertical_padding">
<ImageView
android:id="@+id/menu_header_image"
android:layout_width="@dimen/revamped_context_menu_header_image_max_size"
android:layout_height="@dimen/revamped_context_menu_header_image_max_size"
android:layout_gravity="top|start"
android:src="@drawable/checkerboard_background"
android:scaleType="fitCenter"
android:importantForAccessibility="no" />
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp">
<!-- Circle background for when we have a favicon or monogram -->
<View
android:id="@+id/circle_background"
android:background="@drawable/tile_view_icon_background_modern"
android:layout_width="@dimen/revamped_context_menu_header_circle_bg_diameter"
android:layout_height="@dimen/revamped_context_menu_header_circle_bg_diameter"
android:layout_margin="@dimen/revamped_context_menu_header_circle_bg_margin"
android:visibility="invisible" />
<org.chromium.ui.widget.RoundedCornerImageView
android:id="@+id/menu_header_image"
android:layout_width="@dimen/revamped_context_menu_header_image_max_size"
android:layout_height="@dimen/revamped_context_menu_header_image_max_size"
android:scaleType="centerInside"
android:importantForAccessibility="no"
app:cornerRadiusTopStart="@dimen/default_rounded_corner_radius"
app:cornerRadiusTopEnd="@dimen/default_rounded_corner_radius"
app:cornerRadiusBottomStart="@dimen/default_rounded_corner_radius"
app:cornerRadiusBottomEnd="@dimen/default_rounded_corner_radius"
app:roundedfillColor="@color/thumbnail_placeholder_on_primary_bg" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:layout_gravity="center_vertical">
<TextView
<!-- TODO(sinansahin): Sync with UX to decide on what to do with cases like RTL text on LTR
device and LTR text on RTL device -->
<org.chromium.ui.widget.TextViewWithLeading
android:id="@+id/menu_header_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="viewStart"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.BlackCaptionDefault"/>
<TextView
android:textAppearance="@style/TextAppearance.BlackCaptionDefault"
app:leading="@dimen/text_size_small_leading" />
<org.chromium.ui.widget.TextViewWithLeading
android:id="@+id/menu_header_url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="viewStart"
android:ellipsize="end"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.BlackCaption"/>
android:textAppearance="@style/TextAppearance.BlackCaption"
app:leading="@dimen/text_size_small_leading" />
</LinearLayout>
</LinearLayout>
\ No newline at end of file
......@@ -10,6 +10,6 @@
android:textAppearance="@style/TextAppearance.BlackTitle1"
android:minHeight="48dp"
android:gravity="center_vertical"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:paddingStart="@dimen/revamped_context_menu_list_lateral_padding"
android:paddingEnd="@dimen/revamped_context_menu_list_lateral_padding"
android:background="?attr/selectableItemBackground"/>
\ No newline at end of file
......@@ -542,8 +542,16 @@
<dimen name="context_menu_selectable_items_min_size">120dp</dimen>
<!-- Revamped Context Menu Dimensions -->
<dimen name="revamped_context_menu_header_image_max_size">64dp</dimen>
<dimen name="revamped_context_menu_lateral_margin">40dp</dimen>
<dimen name="revamped_context_menu_vertical_margin">20dp</dimen>
<dimen name="revamped_context_menu_list_lateral_padding">16dp</dimen>
<dimen name="revamped_context_menu_header_vertical_padding">16dp</dimen>
<dimen name="revamped_context_menu_divider_padding">8dp</dimen>
<dimen name="revamped_context_menu_header_image_max_size">60dp</dimen>
<dimen name="revamped_context_menu_header_circle_bg_diameter">48dp</dimen>
<dimen name="revamped_context_menu_header_circle_bg_margin">6dp</dimen>
<dimen name="revamped_context_menu_header_monogram_text_size">16dp</dimen>
<dimen name="revamped_context_menu_header_monogram_size">26dp</dimen>
<!-- Reader Mode dimensions -->
<!-- Padding surrounding the message. -->
<dimen name="reader_mode_infobar_text_padding">8dp</dimen>
......
......@@ -223,21 +223,35 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator {
*/
public static String createHeaderText(ContextMenuParams params) {
if (!isEmptyUrl(params.getLinkUrl())) {
// The context menu can be created without native library
// being loaded. Only use native URL formatting methods
// if the native libraries have been loaded.
if (BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
.isStartupSuccessfullyCompleted()) {
return UrlFormatter.formatUrlForDisplayOmitHTTPScheme(params.getLinkUrl());
} else {
return params.getLinkUrl();
}
return getUrlText(params);
} else if (!TextUtils.isEmpty(params.getTitleText())) {
return params.getTitleText();
}
return "";
}
/**
* Gets the link of the item or empty text if the Url is empty.
* @return A string with the link or an empty string.
*/
public static String createUrlText(ContextMenuParams params) {
if (!isEmptyUrl(params.getLinkUrl())) {
return getUrlText(params);
}
return "";
}
private static String getUrlText(ContextMenuParams params) {
// The context menu can be created without native library
// being loaded. Only use native URL formatting methods
// if the native libraries have been loaded.
if (BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
.isStartupSuccessfullyCompleted()) {
return UrlFormatter.formatUrlForDisplayOmitHTTPScheme(params.getLinkUrl());
}
return params.getLinkUrl();
}
@Override
public List<Pair<Integer, List<ContextMenuItem>>> buildContextMenu(
ContextMenu menu, Context context, ContextMenuParams params) {
......
......@@ -23,6 +23,8 @@ import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.task.PostTask;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.favicon.LargeIconBridge;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.share.ShareHelper;
import org.chromium.chrome.browser.share.ShareParams;
import org.chromium.content_public.browser.UiThreadTaskTraits;
......@@ -138,12 +140,13 @@ public class ContextMenuHelper implements OnCreateContextMenuListener {
mOnMenuShown, mOnMenuClosed);
// TODO(sinansahin): This could be pushed in to the menuController.
if (mCurrentContextMenuParams.isImage()) {
getThumbnail(menuController, new Callback<Bitmap>() {
@Override
public void onResult(Bitmap result) {
menuController.onImageThumbnailRetrieved(result);
}
});
getThumbnail(menuController, menuController::onImageThumbnailRetrieved);
} else {
LargeIconBridge iconBridge = new LargeIconBridge(Profile.getLastUsedProfile());
iconBridge.getLargeIconForUrl(mCurrentContextMenuParams.getUrl(),
getActivity().getResources().getDimensionPixelSize(
R.dimen.default_favicon_size),
menuController::onFaviconAvailable);
}
return;
}
......
......@@ -7,16 +7,33 @@ package org.chromium.chrome.browser.contextmenu;
import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.text.SpannableString;
import android.text.TextUtils;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.Callback;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeBaseAppCompatActivity;
import org.chromium.chrome.browser.favicon.IconType;
import org.chromium.chrome.browser.night_mode.GlobalNightModeStateController;
import org.chromium.chrome.browser.omnibox.OmniboxUrlEmphasizer;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.widget.ContextMenuDialog;
import org.chromium.components.security_state.ConnectionSecurityLevel;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
......@@ -44,13 +61,14 @@ public class RevampedContextMenuController
private RevampedContextMenuListAdapter mListAdapter;
private Callback<Integer> mItemClickCallback;
private float mTopContentOffsetPx;
private String mPlainUrl;
/**
* Constructor that also sets the content offset.
*
* @param topContentOffsetPx content offset from the top.
*/
public RevampedContextMenuController(float topContentOffsetPx) {
RevampedContextMenuController(float topContentOffsetPx) {
mTopContentOffsetPx = topContentOffsetPx;
}
......@@ -59,15 +77,16 @@ public class RevampedContextMenuController
List<Pair<Integer, List<ContextMenuItem>>> items, Callback<Integer> onItemClicked,
final Runnable onMenuShown, final Runnable onMenuClosed) {
mItemClickCallback = onItemClicked;
float density = Resources.getSystem().getDisplayMetrics().density;
final Resources resources = activity.getResources();
final float density = resources.getDisplayMetrics().density;
final float touchPointXPx = params.getTriggeringTouchXDp() * density;
final float touchPointYPx = params.getTriggeringTouchYDp() * density;
final View view =
LayoutInflater.from(activity).inflate(R.layout.revamped_context_menu, null);
mContextMenuDialog = createContextMenuDialog(activity, view, touchPointXPx, touchPointYPx);
mContextMenuDialog.setOnShowListener(dialogInterface -> { onMenuShown.run(); });
mContextMenuDialog.setOnDismissListener(dialogInterface -> { onMenuClosed.run(); });
mContextMenuDialog.setOnShowListener(dialogInterface -> onMenuShown.run());
mContextMenuDialog.setOnDismissListener(dialogInterface -> onMenuClosed.run());
// Integer here indicates if the item is the header, a divider, or a row (selectable option)
List<Pair<Integer, ContextMenuItem>> itemList = new ArrayList<>();
......@@ -82,9 +101,31 @@ public class RevampedContextMenuController
}
}
mListAdapter = new RevampedContextMenuListAdapter(itemList);
mListAdapter.setHeaderTitle(params.getTitleText());
mListAdapter.setHeaderUrl(params.getLinkUrl());
String headerTitle = params.getTitleText();
if (TextUtils.isEmpty(headerTitle)) {
headerTitle = params.getLinkText();
}
mPlainUrl = params.getUrl();
CharSequence url = params.getUrl();
if (!TextUtils.isEmpty(url)) {
boolean useDarkColors = !GlobalNightModeStateController.getInstance().isInNightMode();
if (activity instanceof ChromeBaseAppCompatActivity) {
useDarkColors = !((ChromeBaseAppCompatActivity) activity)
.getNightModeStateProvider()
.isInNightMode();
}
SpannableString spannableUrl =
new SpannableString(ChromeContextMenuPopulator.createUrlText(params));
OmniboxUrlEmphasizer.emphasizeUrl(spannableUrl, resources, Profile.getLastUsedProfile(),
ConnectionSecurityLevel.NONE, false, useDarkColors, false);
url = spannableUrl;
}
mListAdapter = new RevampedContextMenuListAdapter(activity, itemList);
mListAdapter.setHeaderTitle(headerTitle);
mListAdapter.setHeaderUrl(url);
RevampedContextMenuListView listView = view.findViewById(R.id.context_menu_list_view);
listView.setAdapter(mListAdapter);
listView.setOnItemClickListener(this);
......@@ -113,17 +154,56 @@ public class RevampedContextMenuController
return dialog;
}
/**
* This adds a checkerboard style background to the image.
* It is useful for the transparent PNGs.
* @return The given image with the checkerboard pattern in the background.
*/
static Bitmap getImageWithCheckerBackground(Resources res, Bitmap image) {
// 1. Create a bitmap for the checkerboard pattern.
Drawable drawable = ApiCompatibilityUtils.getDrawable(
res, org.chromium.chrome.R.drawable.checkerboard_background);
Bitmap tileBitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas tileCanvas = new Canvas(tileBitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
drawable.draw(tileCanvas);
// 2. Create a BitmapDrawable using the checkerboard pattern bitmap.
BitmapDrawable bitmapDrawable = new BitmapDrawable(res, tileBitmap);
bitmapDrawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
bitmapDrawable.setBounds(0, 0, image.getWidth(), image.getHeight());
// 3. Create a bitmap-backed canvas for the final image.
Bitmap bitmap =
Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
// 4. Paint the checkerboard background into the final canvas
bitmapDrawable.draw(canvas);
// 5. Draw the image on top.
Paint paint = new Paint();
paint.setAntiAlias(true);
canvas.drawBitmap(image, new Matrix(), paint);
return bitmap;
}
/**
* This is called when the thumbnail is fetched and ready to display.
* @param thumbnail The bitmap received that will be displayed as the header image.
*/
public void onImageThumbnailRetrieved(Bitmap thumbnail) {
if (thumbnail != null) {
mListAdapter.getHeaderImage().setImageBitmap(thumbnail);
} else {
// TODO(sinansahin): Handle the failed image loads differently.
mListAdapter.getHeaderImage().setImageResource(R.drawable.sad_tab);
}
void onImageThumbnailRetrieved(Bitmap thumbnail) {
mListAdapter.onImageThumbnailRetrieved(thumbnail);
}
/**
* See {@link org.chromium.chrome.browser.favicon.LargeIconBridge#getLargeIconForUrl}
*/
void onFaviconAvailable(@Nullable Bitmap icon, @ColorInt int fallbackColor,
boolean isColorDefault, @IconType int iconType) {
mListAdapter.onFaviconAvailable(icon, fallbackColor, mPlainUrl);
}
@Override
......
......@@ -4,16 +4,22 @@
package org.chromium.chrome.browser.contextmenu;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.support.annotation.ColorInt;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.widget.RoundedIconGenerator;
import org.chromium.ui.widget.RoundedCornerImageView;
import java.util.List;
......@@ -23,10 +29,17 @@ class RevampedContextMenuListAdapter extends BaseAdapter {
private final List<Pair<Integer, ContextMenuItem>> mMenuItems;
private String mHeaderTitle;
private String mHeaderUrl;
private ImageView mHeaderImage;
private CharSequence mHeaderUrl;
private RoundedCornerImageView mHeaderImage;
private Bitmap mHeaderBitmap;
public RevampedContextMenuListAdapter(List<Pair<Integer, ContextMenuItem>> menuItems) {
private boolean mIsHeaderImageThumbnail;
private Context mContext;
public RevampedContextMenuListAdapter(
Context context, List<Pair<Integer, ContextMenuItem>> menuItems) {
mContext = context;
mMenuItems = menuItems;
}
......@@ -70,6 +83,12 @@ class RevampedContextMenuListAdapter extends BaseAdapter {
mHeaderImage = convertView.findViewById(R.id.menu_header_image);
// We should've cached the bitmap if the header wasn't ready when we received a
// thumbnail, favicon, or monogram. We can set the image to the cached bitmap here.
if (mHeaderBitmap != null) {
setHeaderImage(mHeaderBitmap);
}
TextView titleText = convertView.findViewById(R.id.menu_header_title);
titleText.setText(mHeaderTitle);
......@@ -98,8 +117,7 @@ class RevampedContextMenuListAdapter extends BaseAdapter {
}
} else if (getItem(position).first
== RevampedContextMenuController.ListItemType.DIVIDER) {
// TODO(sinansahin): divider_preference can be renamed to horizontal_divider
layout = R.layout.divider_preference;
layout = R.layout.context_menu_divider;
convertView = LayoutInflater.from(parent.getContext()).inflate(layout, null);
} else {
layout = R.layout.revamped_context_menu_row;
......@@ -117,12 +135,72 @@ class RevampedContextMenuListAdapter extends BaseAdapter {
mHeaderTitle = headerTitle;
}
public void setHeaderUrl(String headerUrl) {
public void setHeaderUrl(CharSequence headerUrl) {
mHeaderUrl = headerUrl;
}
public ImageView getHeaderImage() {
return mHeaderImage;
/**
* This is called when the thumbnail is fetched and ready to display.
* @param thumbnail The bitmap received that will be displayed as the header image.
*/
void onImageThumbnailRetrieved(Bitmap thumbnail) {
mIsHeaderImageThumbnail = true;
if (thumbnail != null) {
setHeaderImage(RevampedContextMenuController.getImageWithCheckerBackground(
mContext.getResources(), thumbnail));
}
// TODO(sinansahin): Handle the case where the retrieval of the thumbnail fails.
}
void onFaviconAvailable(@Nullable Bitmap icon, @ColorInt int fallbackColor, String iconUrl) {
// If we didn't get a favicon, generate a monogram instead
if (icon == null) {
RoundedIconGenerator iconGenerator = createRoundedIconGenerator(fallbackColor);
icon = iconGenerator.generateIconForUrl(iconUrl);
}
mIsHeaderImageThumbnail = false;
final int size = mContext.getResources().getDimensionPixelSize(
R.dimen.revamped_context_menu_header_monogram_size);
if (icon.getWidth() > size) {
icon = Bitmap.createScaledBitmap(icon, size, size, true);
}
setHeaderImage(icon);
}
private void setHeaderImage(Bitmap bitmap) {
// If the HeaderImage hasn't been inflated by the time we receive the bitmap,
// cache the bitmap received to be set in #getView later.
if (mHeaderImage == null) {
mHeaderBitmap = bitmap;
return;
}
// Clear the loading background color now that we have the real image.
mHeaderImage.setRoundedFillColor(android.R.color.transparent);
if (mIsHeaderImageThumbnail) {
mHeaderImage.setImageBitmap(bitmap);
return;
}
((View) mHeaderImage.getParent())
.findViewById(R.id.circle_background)
.setVisibility(View.VISIBLE);
mHeaderImage.setImageBitmap(bitmap);
}
private RoundedIconGenerator createRoundedIconGenerator(@ColorInt int iconColor) {
final Resources resources = mContext.getResources();
final int iconSize =
resources.getDimensionPixelSize(R.dimen.revamped_context_menu_header_monogram_size);
final int cornerRadius = iconSize / 2;
final int textSize = resources.getDimensionPixelSize(
R.dimen.revamped_context_menu_header_monogram_text_size);
return new RoundedIconGenerator(iconSize, iconSize, cornerRadius, iconColor, textSize);
}
@Override
......
......@@ -34,7 +34,8 @@ public class RevampedContextMenuListView extends ListView {
private int calculateWidth() {
int windowWidthPx = getResources().getDisplayMetrics().widthPixels;
int maxWidth = getResources().getDimensionPixelSize(R.dimen.context_menu_max_width);
int lateralMargin = getResources().getDimensionPixelSize(R.dimen.context_menu_min_padding);
int lateralMargin =
getResources().getDimensionPixelSize(R.dimen.revamped_context_menu_lateral_margin);
return Math.min(maxWidth, windowWidthPx - 2 * lateralMargin);
}
......
......@@ -18,6 +18,7 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.graphics.drawable.shapes.Shape;
import android.support.annotation.ColorRes;
import android.support.annotation.Nullable;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
......@@ -119,6 +120,15 @@ public class RoundedCornerImageView extends ImageView {
updateApplyShader();
}
/**
* Set the fill color resource.
* @param id The color resource id.
*/
public void setRoundedFillColor(@ColorRes int id) {
mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mFillPaint.setColor(getContext().getResources().getColor(id));
}
protected void maybeCreateShader() {
// Only create the shader if we have a rectangle to use as a mask.
Drawable drawable = getDrawable();
......
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