Commit e428a4e1 authored by Friedrich Horschig's avatar Friedrich Horschig Committed by Commit Bot

Move ChipView into own class

This CL is a small step to make chips more reusable. It moves the Chips
view as defined for the Downloads Home into a separate View located in
ui/.
This has very little visible effects:
  * Chip appearance is now consistent for Downloads on Kitkat and older
  * The corner radius of chips is variable (important for accessory)
  * RippleBackgroundHelper allows backgrounds with colored borders

Right now, presubmits will complain about the new text style. I'm open
for any tips where the TextAppearance should be defined.

Bug: 914781
Change-Id: I10b84d933a6e5fc98665e942f75e336bb9cc6bd1
Reviewed-on: https://chromium-review.googlesource.com/c/1380013
Commit-Queue: Friedrich [CET] <fhorschig@chromium.org>
Reviewed-by: default avatarTheresa <twellington@chromium.org>
Cr-Commit-Position: refs/heads/master@{#619938}
parent fcdaba0c
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2018 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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/chip_background_color" />
<stroke android:width="1dp" android:color="@color/chip_stroke_color" />
<corners android:radius="8dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2018 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="32dp"
android:orientation="horizontal"
android:gravity="center_vertical"
android:background="@drawable/chip_bg">
<org.chromium.ui.widget.ChromeImageView
android:id="@+id/icon"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginStart="8dp"
android:gravity="center"
android:scaleType="fitCenter"
app:tint="@color/dark_mode_tint" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:maxLines="1"
android:paddingStart="@dimen/chip_icon_padding"
android:paddingEnd="@dimen/chip_no_icon_padding"
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.DownloadHomeChip" />
</LinearLayout>
...@@ -699,10 +699,6 @@ ...@@ -699,10 +699,6 @@
</style> </style>
<!-- Download Home --> <!-- Download Home -->
<style name="TextAppearance.DownloadHomeChip">
<item name="android:textColor">@color/chip_text_color</item>
<item name="android:textSize">@dimen/text_size_medium</item>
</style>
<style name="DateView"> <style name="DateView">
<item name="android:layout_width">match_parent</item> <item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item> <item name="android:layout_height">wrap_content</item>
......
...@@ -553,12 +553,8 @@ ...@@ -553,12 +553,8 @@
<item type="dimen" name="dialog_fixed_height_minor">100%</item> <item type="dimen" name="dialog_fixed_height_minor">100%</item>
<!-- Chip list --> <!-- Chip list -->
<dimen name="chip_no_icon_padding">16dp</dimen>
<dimen name="chip_icon_padding">8dp</dimen>
<dimen name="chip_list_inter_chip_padding">2.5dp</dimen> <dimen name="chip_list_inter_chip_padding">2.5dp</dimen>
<dimen name="chip_list_side_padding">16dp</dimen> <dimen name="chip_list_side_padding">16dp</dimen>
<item name="chip_background_selected_focused_alpha" format="float" type="dimen">0.12</item>
<item name="chip_background_selected_alpha" format="float" type="dimen">0.06</item>
<!-- Download manager dimensions --> <!-- Download manager dimensions -->
<dimen name="download_manager_ideal_image_width">150dp</dimen> <dimen name="download_manager_ideal_image_width">150dp</dimen>
......
...@@ -7,13 +7,15 @@ package org.chromium.chrome.browser.download.home.filter.chips; ...@@ -7,13 +7,15 @@ package org.chromium.chrome.browser.download.home.filter.chips;
import android.support.annotation.DrawableRes; import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes; import android.support.annotation.StringRes;
import org.chromium.ui.widget.ChipView;
/** /**
* A generic visual representation of a Chip. Most of the visuals are immutable, but the selection * A generic visual representation of a Chip. Most of the visuals are immutable, but the selection
* and enable states are not. * and enable states are not.
*/ */
public class Chip { public class Chip {
/** An id to use for {@link #icon} when there is no icon on the chip. */ /** An id to use for {@link #icon} when there is no icon on the chip. */
public static final int INVALID_ICON_ID = -1; public static final int INVALID_ICON_ID = ChipView.INVALID_ICON_ID;
/** An id used to identify this chip. */ /** An id used to identify this chip. */
public final int id; public final int id;
......
...@@ -3,39 +3,25 @@ ...@@ -3,39 +3,25 @@
// found in the LICENSE file. // found in the LICENSE file.
package org.chromium.chrome.browser.download.home.filter.chips; package org.chromium.chrome.browser.download.home.filter.chips;
import android.content.res.ColorStateList;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.RecyclerView.ViewHolder; import android.support.v7.widget.RecyclerView.ViewHolder;
import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R;
import org.chromium.ui.widget.ChipView;
/** The {@link ViewHolder} responsible for reflecting a {@link Chip} to a {@link View}. */ /** The {@link ViewHolder} responsible for reflecting a {@link Chip} to a {@link View}. */
public class ChipsViewHolder extends ViewHolder { public class ChipsViewHolder extends ViewHolder {
private final int mTextStartPaddingWithIconPx;
private final int mTextStartPaddingWithNoIconPx;
private final TextView mText;
private final ImageView mImage;
/** Builds a ChipsViewHolder around a specific {@link View}. */ /** Builds a ChipsViewHolder around a specific {@link View}. */
private ChipsViewHolder(View itemView) { private ChipsViewHolder(View itemView) {
super(itemView); super(itemView);
}
mText = itemView.findViewById(org.chromium.chrome.R.id.text); private ChipView getChipView() {
mImage = itemView.findViewById(org.chromium.chrome.R.id.icon); assert itemView
instanceof ChipView : "ChipViewHolder doesn't hold ChipView but "
ColorStateList textColors = mText.getTextColors(); + itemView.getClass();
if (textColors != null) ApiCompatibilityUtils.setImageTintList(mImage, textColors); return (ChipView) itemView;
mTextStartPaddingWithIconPx = mText.getResources().getDimensionPixelSize(
org.chromium.chrome.R.dimen.chip_icon_padding);
mTextStartPaddingWithNoIconPx = mText.getResources().getDimensionPixelSize(
org.chromium.chrome.R.dimen.chip_no_icon_padding);
} }
/** /**
...@@ -45,8 +31,8 @@ public class ChipsViewHolder extends ViewHolder { ...@@ -45,8 +31,8 @@ public class ChipsViewHolder extends ViewHolder {
*/ */
public static ChipsViewHolder create(ViewGroup parent, int viewType) { public static ChipsViewHolder create(ViewGroup parent, int viewType) {
assert viewType == 0; assert viewType == 0;
return new ChipsViewHolder(LayoutInflater.from(parent.getContext()) return new ChipsViewHolder(
.inflate(org.chromium.chrome.R.layout.chip, null)); new ChipView(parent.getContext(), R.style.SuggestionChipThemeOverlay));
} }
/** /**
...@@ -56,26 +42,12 @@ public class ChipsViewHolder extends ViewHolder { ...@@ -56,26 +42,12 @@ public class ChipsViewHolder extends ViewHolder {
* @see org.chromium.chrome.browser.modelutil.SimpleRecyclerViewMcp.ViewBinder#onBindViewHolder * @see org.chromium.chrome.browser.modelutil.SimpleRecyclerViewMcp.ViewBinder#onBindViewHolder
*/ */
public void bind(Chip chip) { public void bind(Chip chip) {
itemView.setEnabled(chip.enabled); getChipView().setEnabled(chip.enabled);
mText.setEnabled(chip.enabled); getChipView().setSelected(chip.selected);
mImage.setEnabled(chip.enabled); getChipView().setOnClickListener(v -> chip.chipSelectedListener.run());
getChipView().getInnerTextView().setContentDescription(
itemView.setSelected(chip.selected); getChipView().getResources().getString(chip.contentDescription));
itemView.setOnClickListener(v -> chip.chipSelectedListener.run()); getChipView().getInnerTextView().setText(chip.text);
mText.setContentDescription(mText.getContext().getText(chip.contentDescription)); getChipView().setIcon(chip.icon);
mText.setText(chip.text);
final int textStartPadding;
if (chip.icon == Chip.INVALID_ICON_ID) {
mImage.setVisibility(ViewGroup.GONE);
textStartPadding = mTextStartPaddingWithNoIconPx;
} else {
textStartPadding = mTextStartPaddingWithIconPx;
mImage.setVisibility(ViewGroup.VISIBLE);
mImage.setImageResource(chip.icon);
}
ViewCompat.setPaddingRelative(mText, textStartPadding, mText.getPaddingTop(),
ViewCompat.getPaddingEnd(mText), mText.getPaddingBottom());
} }
} }
...@@ -311,6 +311,7 @@ android_library("ui_full_java") { ...@@ -311,6 +311,7 @@ android_library("ui_full_java") {
"java/src/org/chromium/ui/widget/AnchoredPopupWindow.java", "java/src/org/chromium/ui/widget/AnchoredPopupWindow.java",
"java/src/org/chromium/ui/widget/ButtonCompat.java", "java/src/org/chromium/ui/widget/ButtonCompat.java",
"java/src/org/chromium/ui/widget/CheckableImageView.java", "java/src/org/chromium/ui/widget/CheckableImageView.java",
"java/src/org/chromium/ui/widget/ChipView.java",
"java/src/org/chromium/ui/widget/ChromeBulletSpan.java", "java/src/org/chromium/ui/widget/ChromeBulletSpan.java",
"java/src/org/chromium/ui/widget/ChromeImageView.java", "java/src/org/chromium/ui/widget/ChromeImageView.java",
"java/src/org/chromium/ui/widget/ChromeImageButton.java", "java/src/org/chromium/ui/widget/ChromeImageButton.java",
......
<?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. -->
<selector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="UnusedResources">
<item android:alpha="@dimen/default_pressed_alpha"
android:color="@color/modern_grey_600" android:state_pressed="true"/>
<item android:alpha="@dimen/default_focused_hovered_alpha"
android:color="@color/modern_grey_600" android:state_focused="true" android:state_hovered="true"/>
<item android:alpha="@dimen/default_focused_alpha"
android:color="@color/modern_grey_600" android:state_focused="true"/>
<item android:alpha="@dimen/default_hovered_alpha"
android:color="@color/modern_grey_600" android:state_hovered="true"/>
<item android:color="@android:color/transparent" />
</selector>
...@@ -54,6 +54,33 @@ ...@@ -54,6 +54,33 @@
<item name="buttonRaised">false</item> <item name="buttonRaised">false</item>
</style> </style>
<!-- Chips -->
<style name="SuggestionChipThemeOverlay" tools:ignore="UnusedResources">
<item name="chipStyle">@style/SuggestionChip</item>
</style>
<style name="Chip">
<item name="android:minHeight">@dimen/chip_default_height</item>
<item name="android:gravity">center_vertical</item>
<item name="android:orientation">horizontal</item>
<item name="chipColor">@color/chip_background_color</item>
<item name="rippleColor">@color/chip_ripple_color</item>
</style>
<style name="SuggestionChip" parent="Chip" tools:ignore="UnusedResources">
<item name="cornerRadius">@dimen/chip_corner_radius</item>
</style>
<style name="InputChip" parent="Chip" tools:ignore="UnusedResources">
<item name="cornerRadius">@dimen/chip_default_height</item>
</style>
<style name="ChipTextView" tools:ignore="UnusedResources">
<item name="android:gravity">center</item>
<item name="android:maxLines">1</item>
<item name="android:paddingStart">@dimen/chip_icon_padding</item>
<item name="android:paddingEnd">@dimen/chip_no_icon_padding</item>
<item name="android:textAlignment">center</item>
</style>
<!-- Used by Chrome and Content --> <!-- Used by Chrome and Content -->
<!-- TODO(huayinz): Update prefixes for text appearance styles in ui/android. --> <!-- TODO(huayinz): Update prefixes for text appearance styles in ui/android. -->
<style name="TextAppearance" parent="android:TextAppearance" tools:ignore="UnusedResources" /> <style name="TextAppearance" parent="android:TextAppearance" tools:ignore="UnusedResources" />
...@@ -173,6 +200,12 @@ ...@@ -173,6 +200,12 @@
<item name="android:textSize">@dimen/text_size_small</item> <item name="android:textSize">@dimen/text_size_small</item>
</style> </style>
<!-- Chip Text Styles -->
<style name="TextAppearance.ChipText" parent="TextAppearance.RobotoMediumStyle">
<item name="android:textColor">@color/chip_text_color</item>
<item name="android:textSize">@dimen/text_size_medium</item>
</style>
<!-- Dividers --> <!-- Dividers -->
<style name="HorizontalDivider" <style name="HorizontalDivider"
tools:ignore="UnusedResources"> tools:ignore="UnusedResources">
......
...@@ -20,6 +20,15 @@ ...@@ -20,6 +20,15 @@
<attr name="buttonRaised" format="boolean"/> <attr name="buttonRaised" format="boolean"/>
</declare-styleable> </declare-styleable>
<declare-styleable name="ChipView">
<attr name="chipColor" format="color"/>
<attr name="chipStyle" format="reference"/>
<attr name="cornerRadius" format="reference|dimension"/>
<attr name="iconWidth" format="reference|dimension"/>
<attr name="iconHeight" format="reference|dimension"/>
<attr name="rippleColor" format="color"/>
</declare-styleable>
<declare-styleable name="TextViewWithLeading"> <declare-styleable name="TextViewWithLeading">
<attr name="leading" format="reference|dimension"/> <attr name="leading" format="reference|dimension"/>
</declare-styleable> </declare-styleable>
......
...@@ -23,6 +23,17 @@ ...@@ -23,6 +23,17 @@
<item name="default_focused_alpha" format="float" type="dimen">0.06</item> <item name="default_focused_alpha" format="float" type="dimen">0.06</item>
<item name="default_hovered_alpha" format="float" type="dimen">0.04</item> <item name="default_hovered_alpha" format="float" type="dimen">0.04</item>
<!-- Chips default measures -->
<dimen name="chip_border_width">1dp</dimen>
<dimen name="chip_corner_radius">8dp</dimen>
<dimen name="chip_default_height">32dp</dimen>
<dimen name="chip_no_icon_padding">16dp</dimen>
<dimen name="chip_icon_padding">8dp</dimen>
<item name="chip_background_selected_focused_alpha" format="float" type="dimen">0.12</item>
<item name="chip_background_selected_alpha" format="float" type="dimen">0.06</item>
<dimen name="chip_icon_size">20dp</dimen>
<!-- Dropdown default measures -->
<dimen name="dropdown_item_height">50dp</dimen> <dimen name="dropdown_item_height">50dp</dimen>
<dimen name="dropdown_item_divider_height">1px</dimen> <dimen name="dropdown_item_divider_height">1px</dimen>
<dimen name="dropdown_item_label_margin">10dp</dimen> <dimen name="dropdown_item_label_margin">10dp</dimen>
...@@ -38,6 +49,9 @@ ...@@ -38,6 +49,9 @@
<!-- Divider Dimensions --> <!-- Divider Dimensions -->
<dimen name="divider_height">1dp</dimen> <dimen name="divider_height">1dp</dimen>
<!-- Misc -->
<dimen name="default_ripple_background_border_size">0dp</dimen>
<!-- <!--
Fallback values if the corresponding com.android.internal.R dimensions Fallback values if the corresponding com.android.internal.R dimensions
cannot be retrieved by name. cannot be retrieved by name.
......
...@@ -68,7 +68,8 @@ public class ButtonCompat extends AppCompatButton { ...@@ -68,7 +68,8 @@ public class ButtonCompat extends AppCompatButton {
boolean buttonRaised = a.getBoolean(R.styleable.ButtonCompat_buttonRaised, true); boolean buttonRaised = a.getBoolean(R.styleable.ButtonCompat_buttonRaised, true);
a.recycle(); a.recycle();
mRippleBackgroundHelper = new RippleBackgroundHelper(this, buttonColorId, rippleColorId); mRippleBackgroundHelper = new RippleBackgroundHelper(this, buttonColorId, rippleColorId,
getResources().getDimensionPixelSize(R.dimen.button_compat_corner_radius));
setRaised(buttonRaised); setRaised(buttonRaised);
} }
......
// 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.
package org.chromium.ui.widget;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.support.annotation.DrawableRes;
import android.support.annotation.StyleRes;
import android.support.v4.view.MarginLayoutParamsCompat;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.ContextThemeWrapper;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.ui.R;
/** The view responsible for displaying a material chip. */
public class ChipView extends LinearLayout {
/** An id to use for {@link #setIcon(int)} when there is no icon on the chip. */
public static final int INVALID_ICON_ID = -1;
private final int mTextStartPaddingWithIconPx;
private final int mTextStartPaddingWithNoIconPx;
private final RippleBackgroundHelper mRippleBackgroundHelper;
private final TextView mText;
private final ChromeImageView mIcon;
/**
* Constructor for inflating from XML.
*/
public ChipView(Context context, @StyleRes int chipStyle) {
this(context, null, chipStyle);
}
/**
* Constructor for inflating from XML.
*/
public ChipView(Context context, AttributeSet attrs) {
this(context, attrs, R.style.SuggestionChipThemeOverlay);
}
private ChipView(Context context, AttributeSet attrs, @StyleRes int themeOverlay) {
super(new ContextThemeWrapper(context, themeOverlay), attrs, R.attr.chipStyle);
mTextStartPaddingWithIconPx =
getResources().getDimensionPixelSize(R.dimen.chip_icon_padding);
mTextStartPaddingWithNoIconPx =
getResources().getDimensionPixelSize(R.dimen.chip_no_icon_padding);
TypedArray a = getContext().obtainStyledAttributes(
attrs, R.styleable.ChipView, R.attr.chipStyle, 0);
int chipColorId =
a.getResourceId(R.styleable.ChipView_chipColor, R.color.chip_background_color);
int rippleColorId =
a.getResourceId(R.styleable.ChipView_rippleColor, R.color.chip_ripple_color);
int cornerRadius = a.getDimensionPixelSize(R.styleable.ChipView_cornerRadius,
getContext().getResources().getDimensionPixelSize(R.dimen.chip_corner_radius));
int iconWidth = a.getDimensionPixelSize(R.styleable.ChipView_iconWidth,
getResources().getDimensionPixelSize(R.dimen.chip_icon_size));
int iconHeight = a.getDimensionPixelSize(R.styleable.ChipView_iconHeight,
getResources().getDimensionPixelSize(R.dimen.chip_icon_size));
a.recycle();
mIcon = new ChromeImageView(getContext());
LayoutParams lp = new LayoutParams(iconWidth, iconHeight);
MarginLayoutParamsCompat.setMarginStart(lp, mTextStartPaddingWithIconPx);
mIcon.setLayoutParams(lp);
addView(mIcon);
mText = new TextView(new ContextThemeWrapper(getContext(), R.style.ChipTextView));
ApiCompatibilityUtils.setTextAppearance(mText, R.style.TextAppearance_ChipText);
addView(mText);
// Reset icon and background:
mRippleBackgroundHelper = new RippleBackgroundHelper(this, chipColorId, rippleColorId,
cornerRadius, R.color.chip_stroke_color, R.dimen.chip_border_width);
setIcon(INVALID_ICON_ID);
ColorStateList textColors = mText.getTextColors();
if (textColors != null) ApiCompatibilityUtils.setImageTintList(mIcon, textColors);
}
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
if (mRippleBackgroundHelper != null) {
mRippleBackgroundHelper.onDrawableStateChanged();
}
}
/**
* Sets the icon at the start of the chip view.
* @param icon The resource id pointing to the icon.
*/
public void setIcon(@DrawableRes int icon) {
final int textStartPadding;
if (icon == INVALID_ICON_ID) {
mIcon.setVisibility(ViewGroup.GONE);
textStartPadding = mTextStartPaddingWithNoIconPx;
} else {
textStartPadding = mTextStartPaddingWithIconPx;
mIcon.setVisibility(ViewGroup.VISIBLE);
mIcon.setImageResource(icon);
}
ViewCompat.setPaddingRelative(mText, textStartPadding, mText.getPaddingTop(),
ViewCompat.getPaddingEnd(mText), mText.getPaddingBottom());
}
/**
* Returns the {@link TextView} that contains the label of the chip.
* @return A {@link TextView}.
*/
public TextView getInnerTextView() {
return mText;
}
}
...@@ -14,7 +14,9 @@ import android.graphics.drawable.RippleDrawable; ...@@ -14,7 +14,9 @@ import android.graphics.drawable.RippleDrawable;
import android.os.Build; import android.os.Build;
import android.support.annotation.ColorInt; import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes; import android.support.annotation.ColorRes;
import android.support.annotation.DimenRes;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.Px;
import android.support.v4.graphics.ColorUtils; import android.support.v4.graphics.ColorUtils;
import android.support.v4.graphics.drawable.DrawableCompat; import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.content.res.AppCompatResources; import android.support.v7.content.res.AppCompatResources;
...@@ -42,49 +44,43 @@ class RippleBackgroundHelper { ...@@ -42,49 +44,43 @@ class RippleBackgroundHelper {
// Used for applying tint on pre-L versions. // Used for applying tint on pre-L versions.
private Drawable mBackgroundDrawablePreL; private Drawable mBackgroundDrawablePreL;
private Drawable mRippleDrawablePreL; private Drawable mRippleDrawablePreL;
private Drawable mBorderDrawablePreL;
/** /**
* @param view The {@link View} on which background will be applied. * @param view The {@link View} on which background will be applied.
* @param backgroundColorResId The resource id of the background color. * @param backgroundColorResId The resource id of the background color.
* @param rippleColorResId The resource id of the ripple color. * @param rippleColorResId The resource id of the ripple color.
* @param cornerRadius The corner radius in pixels of the background drawable.
*/ */
RippleBackgroundHelper( RippleBackgroundHelper(View view, @ColorRes int backgroundColorResId,
View view, @ColorRes int backgroundColorResId, @ColorRes int rippleColorResId) { @ColorRes int rippleColorResId, @Px int cornerRadius) {
mView = view; this(view, backgroundColorResId, rippleColorResId, cornerRadius,
ColorStateList rippleColorList = android.R.color.transparent, R.dimen.default_ripple_background_border_size);
AppCompatResources.getColorStateList(view.getContext(), rippleColorResId); }
int cornerRadius =
view.getResources().getDimensionPixelSize(R.dimen.button_compat_corner_radius);
ColorStateList backgroundColorList =
AppCompatResources.getColorStateList(view.getContext(), backgroundColorResId);
mBackgroundGradient = new GradientDrawable();
mBackgroundGradient.setCornerRadius(cornerRadius);
Drawable wrappedDrawable; /**
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { * @param view The {@link View} on which background will be applied.
mBackgroundDrawablePreL = DrawableCompat.wrap(mBackgroundGradient); * @param backgroundColorResId The resource id of the background color.
GradientDrawable rippleGradient = new GradientDrawable(); * @param rippleColorResId The resource id of the ripple color.
rippleGradient.setCornerRadius(cornerRadius); * @param cornerRadius The corner radius in pixels of the background drawable.
mRippleDrawablePreL = DrawableCompat.wrap(rippleGradient); * @param borderColorResId The resource id of the border color.
DrawableCompat.setTintList(mRippleDrawablePreL, rippleColorList); * @param borderSizeDimenId The resource id of the border size.
wrappedDrawable = new LayerDrawable( */
new Drawable[] {mBackgroundDrawablePreL, mRippleDrawablePreL}); RippleBackgroundHelper(View view, @ColorRes int backgroundColorResId,
} else { @ColorRes int rippleColorResId, @Px int cornerRadius, @ColorRes int borderColorResId,
GradientDrawable mask = new GradientDrawable(); @DimenRes int borderSizeDimenId) {
mask.setCornerRadius(cornerRadius); mView = view;
mask.setColor(Color.WHITE);
wrappedDrawable = new RippleDrawable(
convertToRippleDrawableColorList(rippleColorList), mBackgroundGradient, mask);
}
int paddingLeft = mView.getPaddingLeft(); int paddingLeft = mView.getPaddingLeft();
int paddingTop = mView.getPaddingTop(); int paddingTop = mView.getPaddingTop();
int paddingRight = mView.getPaddingRight(); int paddingRight = mView.getPaddingRight();
int paddingBottom = mView.getPaddingBottom(); int paddingBottom = mView.getPaddingBottom();
mView.setBackground(wrappedDrawable); mView.setBackground(createBackgroundDrawable(
setBackgroundColor(backgroundColorList); AppCompatResources.getColorStateList(view.getContext(), rippleColorResId),
AppCompatResources.getColorStateList(view.getContext(), borderColorResId),
view.getResources().getDimensionPixelSize(borderSizeDimenId), cornerRadius));
setBackgroundColor(
AppCompatResources.getColorStateList(view.getContext(), backgroundColorResId));
// On KitKat, setting the background on the view can cause padding reset. Save the padding // On KitKat, setting the background on the view can cause padding reset. Save the padding
// and re-apply after background is set. // and re-apply after background is set.
...@@ -93,6 +89,51 @@ class RippleBackgroundHelper { ...@@ -93,6 +89,51 @@ class RippleBackgroundHelper {
} }
} }
/**
* This initializes all members with new drawables needed to display/update a ripple effect.
* @param rippleColorList A {@link ColorStateList} that is used for the ripple effect.
* @param borderColorList A {@link ColorStateList} that is used for the border.
* @param borderSize The border width in pixels.
* @param cornerRadius The corner radius in pixels.
* @return The {@link GradientDrawable}/{@link LayerDrawable} to be used as ripple background.
*/
private Drawable createBackgroundDrawable(ColorStateList rippleColorList,
ColorStateList borderColorList, @Px int borderSize, @Px int cornerRadius) {
mBackgroundGradient = new GradientDrawable();
mBackgroundGradient.setCornerRadius(cornerRadius);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (borderSize > 0) mBackgroundGradient.setStroke(borderSize, borderColorList);
GradientDrawable mask = new GradientDrawable();
mask.setCornerRadius(cornerRadius);
mask.setColor(Color.WHITE);
return new RippleDrawable(
convertToRippleDrawableColorList(rippleColorList), mBackgroundGradient, mask);
}
// Pre-L, create a background drawable and overlay it by a ripple drawable.
GradientDrawable rippleGradient = new GradientDrawable();
rippleGradient.setCornerRadius(cornerRadius);
mBackgroundDrawablePreL = DrawableCompat.wrap(mBackgroundGradient);
mRippleDrawablePreL = DrawableCompat.wrap(rippleGradient);
DrawableCompat.setTintList(mRippleDrawablePreL, rippleColorList);
if (borderSize == 0) {
return new LayerDrawable(new Drawable[] {mBackgroundDrawablePreL, mRippleDrawablePreL});
}
// If the background is overlaid by a border. The border is in a separate GradientDrawable
// to apply ColorStateLists independently from ripple and background.
GradientDrawable borderGradient = new GradientDrawable();
borderGradient.setCornerRadius(cornerRadius);
borderGradient.setColor(mView.getResources().getColor(android.R.color.transparent));
borderGradient.setStroke(borderSize,
borderColorList.getColorForState(
mView.getDrawableState(), borderColorList.getDefaultColor()));
mBorderDrawablePreL = DrawableCompat.wrap(borderGradient);
DrawableCompat.setTintList(mBorderDrawablePreL, borderColorList);
return new LayerDrawable(
new Drawable[] {mBackgroundDrawablePreL, mBorderDrawablePreL, mRippleDrawablePreL});
}
/** /**
* @param color The {@link ColorStateList} to be set as the background color on the background * @param color The {@link ColorStateList} to be set as the background color on the background
* drawable. * drawable.
...@@ -118,6 +159,7 @@ class RippleBackgroundHelper { ...@@ -118,6 +159,7 @@ class RippleBackgroundHelper {
int[] state = mView.getDrawableState(); int[] state = mView.getDrawableState();
mBackgroundDrawablePreL.setState(state); mBackgroundDrawablePreL.setState(state);
mRippleDrawablePreL.setState(state); mRippleDrawablePreL.setState(state);
if (mBorderDrawablePreL != null) mBorderDrawablePreL.setState(state);
} }
/** /**
......
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