Commit 7505272e authored by Becky Zhou's avatar Becky Zhou Committed by Commit Bot

[Snowflake] Update button widget to match v2 ripple color

+ Add support for ripple color on borderless button
+ Refactor out background drawable logic to another class

Bug: 849126, 856244
Change-Id: I5960714129110bea0b9d284779f71592d90e4a36
Reviewed-on: https://chromium-review.googlesource.com/c/1293172Reviewed-by: default avatarTheresa <twellington@chromium.org>
Commit-Queue: Becky Zhou <huayinz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#601756}
parent c50e7d35
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
--> -->
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="@dimen/chip_background_disabled_alpha" <item android:alpha="@dimen/default_disabled_alpha"
android:color="@color/modern_grey_100" android:color="@color/modern_grey_100"
android:state_enabled="false" /> android:state_enabled="false" />
<item android:alpha="@dimen/chip_background_selected_focused_alpha" <item android:alpha="@dimen/chip_background_selected_focused_alpha"
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
<item android:alpha="@dimen/chip_background_selected_alpha" <item android:alpha="@dimen/chip_background_selected_alpha"
android:color="@color/modern_blue_600" android:color="@color/modern_blue_600"
android:state_selected="true" /> android:state_selected="true" />
<item android:alpha="@dimen/chip_background_focused_alpha" <item android:alpha="@dimen/default_focused_alpha"
android:color="@color/modern_grey_800" android:color="@color/modern_grey_800"
android:state_focused="true" /> android:state_focused="true" />
<item android:color="@android:color/white" /> <item android:color="@android:color/white" />
......
...@@ -9,21 +9,15 @@ ...@@ -9,21 +9,15 @@
android:orientation="vertical" android:orientation="vertical"
android:paddingBottom="8dp" > android:paddingBottom="8dp" >
<Button <org.chromium.ui.widget.ButtonCompat
android:id="@+id/clear_browsing_data_button" android:id="@+id/clear_browsing_data_button"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="top" android:layout_gravity="top"
style="@style/ButtonCompatBorderless" android:padding="@dimen/list_item_default_margin"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingStart="@dimen/list_item_default_margin"
android:paddingEnd="@dimen/list_item_default_margin"
android:gravity="center_vertical|start" android:gravity="center_vertical|start"
android:text="@string/open_clear_browsing_data_dialog_button" android:text="@string/open_clear_browsing_data_dialog_button"
android:textAllCaps="true" style="@style/TextButton" />
android:textColor="@color/blue_when_enabled"
android:textSize="@dimen/text_size_medium" />
<View style="@style/HorizontalDivider" /> <View style="@style/HorizontalDivider" />
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
<org.chromium.ui.widget.ButtonCompat <org.chromium.ui.widget.ButtonCompat
android:id="@+id/signin_promo_signin_button" android:id="@+id/signin_promo_signin_button"
style="@style/SigninButtonCompat" style="@style/FilledButton.Flat"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="36dp" android:layout_height="36dp"
android:layout_marginBottom="6dp" android:layout_marginBottom="6dp"
......
...@@ -600,11 +600,6 @@ ...@@ -600,11 +600,6 @@
<item name="android:textAppearance">@style/BlackBody</item> <item name="android:textAppearance">@style/BlackBody</item>
<item name="android:layout_gravity">start</item> <item name="android:layout_gravity">start</item>
</style> </style>
<style name="SigninButtonCompat">
<item name="android:textAppearance">@style/WhiteButtonText</item>
<item name="buttonColor">@color/light_active_color</item>
<item name="buttonRaised">false</item>
</style>
<style name="SigninButtonBorderlessRegular"> <style name="SigninButtonBorderlessRegular">
<item name="android:background">?android:attr/selectableItemBackground</item> <item name="android:background">?android:attr/selectableItemBackground</item>
<item name="android:paddingStart">0dp</item> <item name="android:paddingStart">0dp</item>
......
...@@ -535,8 +535,6 @@ ...@@ -535,8 +535,6 @@
<dimen name="chip_icon_padding">8dp</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_disabled_alpha" format="float" type="dimen">0.38</item>
<item name="chip_background_focused_alpha" format="float" type="dimen">0.06</item>
<item name="chip_background_selected_focused_alpha" format="float" type="dimen">0.12</item> <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> <item name="chip_background_selected_alpha" format="float" type="dimen">0.06</item>
......
...@@ -7,11 +7,11 @@ package org.chromium.chrome.browser.infobar; ...@@ -7,11 +7,11 @@ package org.chromium.chrome.browser.infobar;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewCompat;
import android.support.v7.content.res.AppCompatResources;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageView; import android.widget.ImageView;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.ContextUtils; import org.chromium.base.ContextUtils;
import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.CalledByNative;
import org.chromium.chrome.R; import org.chromium.chrome.R;
...@@ -72,8 +72,8 @@ public class AppBannerInfoBarAndroid extends ConfirmInfoBar implements View.OnCl ...@@ -72,8 +72,8 @@ public class AppBannerInfoBarAndroid extends ConfirmInfoBar implements View.OnCl
Context context = getContext(); Context context = getContext();
if (mAppData != null) { if (mAppData != null) {
// Native app. // Native app.
layout.getPrimaryButton().setButtonColor(ApiCompatibilityUtils.getColor( layout.getPrimaryButton().setButtonColor(AppCompatResources.getColorStateList(
context.getResources(), R.color.app_banner_install_button_bg)); context, R.color.app_banner_install_button_bg));
mMessageLayout.addRatingBar(mAppData.rating()); mMessageLayout.addRatingBar(mAppData.rating());
mMessageLayout.setContentDescription(context.getString( mMessageLayout.setContentDescription(context.getString(
R.string.app_banner_view_native_app_accessibility, mAppTitle, R.string.app_banner_view_native_app_accessibility, mAppTitle,
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
package org.chromium.chrome.browser.infobar; package org.chromium.chrome.browser.infobar;
import android.support.v7.content.res.AppCompatResources;
import android.widget.ImageView; import android.widget.ImageView;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.CalledByNative;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.instantapps.InstantAppsBannerData; import org.chromium.chrome.browser.instantapps.InstantAppsBannerData;
...@@ -33,9 +33,8 @@ public class InstantAppsInfoBar extends ConfirmInfoBar { ...@@ -33,9 +33,8 @@ public class InstantAppsInfoBar extends ConfirmInfoBar {
layout.setMessage(mData.getAppName()); layout.setMessage(mData.getAppName());
layout.getMessageLayout().addDescription( layout.getMessageLayout().addDescription(
UrlFormatter.formatUrlForSecurityDisplayOmitScheme(mData.getUrl())); UrlFormatter.formatUrlForSecurityDisplayOmitScheme(mData.getUrl()));
layout.getPrimaryButton() layout.getPrimaryButton().setButtonColor(AppCompatResources.getColorStateList(
.setButtonColor(ApiCompatibilityUtils.getColor(getContext().getResources(), getContext(), R.color.app_banner_install_button_bg));
R.color.app_banner_install_button_bg));
} }
@Override @Override
......
...@@ -64,18 +64,15 @@ public final class DualControlLayout extends ViewGroup { ...@@ -64,18 +64,15 @@ public final class DualControlLayout extends ViewGroup {
*/ */
public static Button createButtonForLayout( public static Button createButtonForLayout(
Context context, boolean isPrimary, String text, OnClickListener listener) { Context context, boolean isPrimary, String text, OnClickListener listener) {
int buttonColor =
ApiCompatibilityUtils.getColor(context.getResources(), R.color.light_active_color);
if (isPrimary) { if (isPrimary) {
ButtonCompat primaryButton = new ButtonCompat(context, buttonColor, false); ButtonCompat primaryButton =
new ButtonCompat(context, R.style.FilledButtonThemeOverlay_Flat);
primaryButton.setId(R.id.button_primary); primaryButton.setId(R.id.button_primary);
primaryButton.setOnClickListener(listener); primaryButton.setOnClickListener(listener);
primaryButton.setText(text); primaryButton.setText(text);
ApiCompatibilityUtils.setTextAppearance(primaryButton, R.style.WhiteButtonText);
return primaryButton; return primaryButton;
} else { } else {
Button secondaryButton = ButtonCompat.createBorderlessButton(context); Button secondaryButton = new ButtonCompat(context, R.style.TextButtonThemeOverlay);
secondaryButton.setId(R.id.button_secondary); secondaryButton.setId(R.id.button_secondary);
secondaryButton.setOnClickListener(listener); secondaryButton.setOnClickListener(listener);
secondaryButton.setText(text); secondaryButton.setText(text);
......
...@@ -313,6 +313,7 @@ android_library("ui_full_java") { ...@@ -313,6 +313,7 @@ android_library("ui_full_java") {
"java/src/org/chromium/ui/widget/ChromeBulletSpan.java", "java/src/org/chromium/ui/widget/ChromeBulletSpan.java",
"java/src/org/chromium/ui/widget/OptimizedFrameLayout.java", "java/src/org/chromium/ui/widget/OptimizedFrameLayout.java",
"java/src/org/chromium/ui/widget/RectProvider.java", "java/src/org/chromium/ui/widget/RectProvider.java",
"java/src/org/chromium/ui/widget/RippleBackgroundHelper.java",
"java/src/org/chromium/ui/widget/RoundedCornerImageView.java", "java/src/org/chromium/ui/widget/RoundedCornerImageView.java",
"java/src/org/chromium/ui/widget/TextViewWithClickableSpans.java", "java/src/org/chromium/ui/widget/TextViewWithClickableSpans.java",
"java/src/org/chromium/ui/widget/TextViewWithLeading.java", "java/src/org/chromium/ui/widget/TextViewWithLeading.java",
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
found in the LICENSE file. found in the LICENSE file.
--> -->
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false" android:color="@color/black_alpha_38" /> <item android:alpha="@dimen/default_disabled_alpha"
android:color="@color/modern_grey_800" android:state_enabled="false" />
<item android:color="@color/default_text_color_link"/> <item android:color="@color/default_text_color_link"/>
</selector> </selector>
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
found in the LICENSE file. found in the LICENSE file.
--> -->
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="@dimen/disabled_text_alpha" android:color="@color/default_text_color" <item android:alpha="@dimen/default_disabled_alpha"
android:state_enabled="false"/> android:color="@color/default_text_color" android:state_enabled="false"/>
<item android:color="@color/default_text_color" /> <item android:color="@color/default_text_color" />
</selector> </selector>
\ No newline at end of file
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
found in the LICENSE file. found in the LICENSE file.
--> -->
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="@dimen/disabled_text_alpha" <item android:alpha="@dimen/default_disabled_alpha"
android:color="@color/default_text_color_secondary" android:state_enabled="false"/> android:color="@color/default_text_color_secondary" android:state_enabled="false"/>
<item android:color="@color/default_text_color_secondary" /> <item android:color="@color/default_text_color_secondary" />
</selector> </selector>
\ 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. -->
<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="@android:color/white" android:state_pressed="true"/>
<item android:alpha="@dimen/default_focused_hovered_alpha"
android:color="@android:color/white" android:state_focused="true" android:state_hovered="true"/>
<item android:alpha="@dimen/default_focused_alpha"
android:color="@android:color/white" android:state_focused="true"/>
<item android:alpha="@dimen/default_hovered_alpha"
android:color="@android:color/white" android:state_hovered="true"/>
<item android:color="@android:color/transparent" />
</selector>
\ 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. -->
<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_blue_600" android:state_pressed="true"/>
<item android:alpha="@dimen/default_focused_hovered_alpha"
android:color="@color/modern_blue_600" android:state_focused="true" android:state_hovered="true"/>
<item android:alpha="@dimen/default_focused_alpha"
android:color="@color/modern_blue_600" android:state_focused="true"/>
<item android:alpha="@dimen/default_hovered_alpha"
android:color="@color/modern_blue_600" android:state_hovered="true"/>
<item android:color="@android:color/transparent" />
</selector>
\ No newline at end of file
...@@ -5,5 +5,5 @@ ...@@ -5,5 +5,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#fff" /> <solid android:color="#fff" />
<corners android:radius="2dp" /> <corners android:radius="@dimen/button_compat_corner_radius" />
</shape> </shape>
...@@ -12,12 +12,16 @@ ...@@ -12,12 +12,16 @@
</style> </style>
<!-- Buttons --> <!-- Buttons -->
<style name="ButtonCompatOverlay"> <style name="FilledButtonThemeOverlay">
<item name="android:buttonStyle">@style/ButtonCompat</item> <item name="android:buttonStyle">@style/FilledButton</item>
</style> </style>
<style name="ButtonCompatBorderlessOverlay"> <style name="FilledButtonThemeOverlay.Flat" tools:ignore="UnusedResources">
<item name="android:buttonStyle">@style/ButtonCompatBorderless</item> <item name="android:buttonStyle">@style/FilledButton.Flat</item>
</style> </style>
<style name="TextButtonThemeOverlay" tools:ignore="UnusedResources">
<item name="android:buttonStyle">@style/TextButton</item>
</style>
<style name="ButtonCompatBase"> <style name="ButtonCompatBase">
<item name="android:minWidth">88dp</item> <item name="android:minWidth">88dp</item>
<item name="android:minHeight">36dp</item> <item name="android:minHeight">36dp</item>
...@@ -29,10 +33,27 @@ ...@@ -29,10 +33,27 @@
<item name="android:clickable">true</item> <item name="android:clickable">true</item>
<item name="android:gravity">center_vertical|center_horizontal</item> <item name="android:gravity">center_vertical|center_horizontal</item>
</style> </style>
<style name="ButtonCompat" parent="ButtonCompatBase"> <style name="FilledButton" parent="ButtonCompatBase" tools:ignore="UnusedResources">
<item name="android:textAppearance">@style/WhiteButtonText</item>
<item name="buttonColor">@color/blue_when_enabled</item>
<item name="rippleColor">@color/filled_button_ripple_color</item>
<item name="buttonRaised">true</item>
</style>
<style name="FilledButton.Flat" tools:ignore="UnusedResources">
<item name="buttonRaised">false</item>
</style>
<style name="TextButton" parent="ButtonCompatBase" tools:ignore="UnusedResources">
<item name="android:textAppearance">@style/BlueButtonText2</item>
<item name="buttonColor">@android:color/transparent</item>
<item name="rippleColor">@color/text_button_ripple_color</item>
<item name="buttonRaised">false</item>
</style>
<!-- TODO(huayinz): Remove these once button unification is done. -->
<style name="ButtonCompat" parent="ButtonCompatBase" tools:ignore="UnusedResources">
<item name="android:background">@drawable/button_compat_shape</item> <item name="android:background">@drawable/button_compat_shape</item>
</style> </style>
<style name="ButtonCompatBorderless" parent="ButtonCompat"> <style name="ButtonCompatBorderless" parent="ButtonCompat" tools:ignore="UnusedResources">
<item name="android:background">?android:attr/selectableItemBackground</item> <item name="android:background">?android:attr/selectableItemBackground</item>
</style> </style>
......
...@@ -13,19 +13,24 @@ ...@@ -13,19 +13,24 @@
<enum name="apart" value="2" /> <enum name="apart" value="2" />
</attr> </attr>
</declare-styleable> </declare-styleable>
<declare-styleable name="ButtonCompat"> <declare-styleable name="ButtonCompat">
<attr name="buttonColor" format="reference|color"/> <attr name="buttonColor" format="color"/>
<attr name="rippleColor" format="color"/>
<attr name="buttonRaised" format="boolean"/> <attr name="buttonRaised" format="boolean"/>
</declare-styleable> </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>
<declare-styleable name="AsyncViewStub"> <declare-styleable name="AsyncViewStub">
<!-- Supply an identifier for the layout resource to inflate when the AsyncViewStub <!-- Supply an identifier for the layout resource to inflate when the AsyncViewStub
becomes visible or when forced to do so. The layout resource must be a becomes visible or when forced to do so. The layout resource must be a
valid reference to a layout. --> valid reference to a layout. -->
<attr name="layout" format="reference" /> <attr name="layout" format="reference" />
</declare-styleable> </declare-styleable>
<declare-styleable name="RoundedCornerImageView"> <declare-styleable name="RoundedCornerImageView">
<attr name="cornerRadiusTopStart" format="dimension" /> <attr name="cornerRadiusTopStart" format="dimension" />
<attr name="cornerRadiusTopEnd" format="dimension" /> <attr name="cornerRadiusTopEnd" format="dimension" />
......
...@@ -12,7 +12,11 @@ ...@@ -12,7 +12,11 @@
<dimen name="text_size_small">12sp</dimen> <dimen name="text_size_small">12sp</dimen>
<!-- Common alpha values --> <!-- Common alpha values -->
<item name="disabled_text_alpha" format="float" type="dimen">0.38</item> <item name="default_disabled_alpha" format="float" type="dimen">0.38</item>
<item name="default_pressed_alpha" format="float" type="dimen">0.10</item>
<item name="default_focused_hovered_alpha" format="float" type="dimen">0.10</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>
<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>
......
...@@ -6,17 +6,14 @@ package org.chromium.ui.widget; ...@@ -6,17 +6,14 @@ package org.chromium.ui.widget;
import android.animation.AnimatorInflater; import android.animation.AnimatorInflater;
import android.animation.StateListAnimator; import android.animation.StateListAnimator;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.RippleDrawable;
import android.os.Build; import android.os.Build;
import android.support.annotation.StyleRes;
import android.support.v7.widget.AppCompatButton;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.ContextThemeWrapper; import android.view.ContextThemeWrapper;
import android.widget.Button;
import org.chromium.ui.R; import org.chromium.ui.R;
...@@ -26,7 +23,7 @@ import org.chromium.ui.R; ...@@ -26,7 +23,7 @@ import org.chromium.ui.R;
* *
* Create a button in Java: * Create a button in Java:
* *
* new ButtonCompat(context, Color.RED); * new ButtonCompat(context, R.style.TextButtonThemeOverlay);
* *
* Create a button in XML: * Create a button in XML:
* *
...@@ -34,68 +31,52 @@ import org.chromium.ui.R; ...@@ -34,68 +31,52 @@ import org.chromium.ui.R;
* android:layout_width="wrap_content" * android:layout_width="wrap_content"
* android:layout_height="wrap_content" * android:layout_height="wrap_content"
* android:text="Click me" * android:text="Click me"
* chrome:buttonColor="#f00" /> * style="@style/TextButton" />
* *
* Note: To ensure the button's shadow is fully visible, you may need to set * Note: To ensure the button's shadow is fully visible, you may need to set
* android:clipToPadding="false" on the button's parent view. * android:clipToPadding="false" on the button's parent view.
*/ */
@TargetApi(Build.VERSION_CODES.LOLLIPOP) public class ButtonCompat extends AppCompatButton {
public class ButtonCompat extends Button { private RippleBackgroundHelper mRippleBackgroundHelper;
private static final float PRE_L_PRESSED_BRIGHTNESS = 0.85f;
private static final int DISABLED_COLOR = 0x424F4F4F;
private final int mCornerRadius;
private int mColor;
/** /**
* Returns a new borderless material-style button. * Constructor for programmatically creating a {@link ButtonCompat}.
* @param context The {@link Context} for this class.
* @param themeOverlay The style resource id that sets android:buttonStyle to specify the button
* style.
*/ */
public static Button createBorderlessButton(Context context) { public ButtonCompat(Context context, @StyleRes int themeOverlay) {
return new Button(new ContextThemeWrapper(context, R.style.ButtonCompatBorderlessOverlay)); this(context, null, themeOverlay);
} }
/** /**
* Constructs a button with the given buttonColor as its background. The button is raised if * Constructor for inflating from XMLs.
* buttonRaised is true.
*/
public ButtonCompat(Context context, int buttonColor, boolean buttonRaised) {
this(context, buttonColor, buttonRaised, null);
}
/**
* Constructor for inflating from XML.
*/ */
public ButtonCompat(Context context, AttributeSet attrs) { public ButtonCompat(Context context, AttributeSet attrs) {
this(context, getColorFromAttributeSet(context, attrs), this(context, attrs, R.style.FilledButtonThemeOverlay);
getRaisedStatusFromAttributeSet(context, attrs), attrs);
} }
private ButtonCompat( private ButtonCompat(Context context, AttributeSet attrs, @StyleRes int themeOverlay) {
Context context, int buttonColor, boolean buttonRaised, AttributeSet attrs) { super(new ContextThemeWrapper(context, themeOverlay), attrs, android.R.attr.buttonStyle);
// To apply the ButtonCompat style to this view, use a ContextThemeWrapper to overlay the
// ButtonCompatThemeOverlay, which simply sets the buttonStyle to @style/ButtonCompat. TypedArray a = getContext().obtainStyledAttributes(
super(new ContextThemeWrapper(context, R.style.ButtonCompatOverlay), attrs); attrs, R.styleable.ButtonCompat, android.R.attr.buttonStyle, 0);
int buttonColorId =
a.getResourceId(R.styleable.ButtonCompat_buttonColor, R.color.blue_when_enabled);
int rippleColorId = a.getResourceId(
R.styleable.ButtonCompat_rippleColor, R.color.filled_button_ripple_color);
boolean buttonRaised = a.getBoolean(R.styleable.ButtonCompat_buttonRaised, true);
a.recycle();
mCornerRadius = mRippleBackgroundHelper = new RippleBackgroundHelper(this, buttonColorId, rippleColorId);
context.getResources().getDimensionPixelSize(R.dimen.button_compat_corner_radius);
getBackground().mutate();
setButtonColor(buttonColor);
setRaised(buttonRaised); setRaised(buttonRaised);
} }
/** /**
* Sets the background color of the button. * Sets the background color of the button.
*/ */
public void setButtonColor(int color) { public void setButtonColor(ColorStateList buttonColorList) {
if (color == mColor) return; mRippleBackgroundHelper.setBackgroundColor(buttonColorList);
mColor = color;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
updateButtonBackgroundL();
} else {
updateButtonBackgroundPreL();
}
} }
/** /**
...@@ -134,59 +115,8 @@ public class ButtonCompat extends Button { ...@@ -134,59 +115,8 @@ public class ButtonCompat extends Button {
@Override @Override
protected void drawableStateChanged() { protected void drawableStateChanged() {
super.drawableStateChanged(); super.drawableStateChanged();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { if (mRippleBackgroundHelper != null) {
updateButtonBackgroundPreL(); mRippleBackgroundHelper.onDrawableStateChanged();
} }
} }
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void updateButtonBackgroundL() {
ColorStateList csl = new ColorStateList(
new int[][] { { -android.R.attr.state_enabled }, {} },
new int[] { DISABLED_COLOR, mColor });
GradientDrawable shape = (GradientDrawable)
((RippleDrawable) getBackground()).getDrawable(0);
shape.mutate();
shape.setCornerRadius(mCornerRadius);
shape.setColor(csl);
}
private void updateButtonBackgroundPreL() {
GradientDrawable background = (GradientDrawable) getBackground();
background.setCornerRadius(mCornerRadius);
background.setColor(getBackgroundColorPreL());
}
private int getBackgroundColorPreL() {
for (int state : getDrawableState()) {
if (state == android.R.attr.state_pressed
|| state == android.R.attr.state_focused
|| state == android.R.attr.state_selected) {
return Color.rgb(
Math.round(Color.red(mColor) * PRE_L_PRESSED_BRIGHTNESS),
Math.round(Color.green(mColor) * PRE_L_PRESSED_BRIGHTNESS),
Math.round(Color.blue(mColor) * PRE_L_PRESSED_BRIGHTNESS));
}
}
for (int state : getDrawableState()) {
if (state == android.R.attr.state_enabled) {
return mColor;
}
}
return DISABLED_COLOR;
}
private static int getColorFromAttributeSet(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ButtonCompat, 0, 0);
int color = a.getColor(R.styleable.ButtonCompat_buttonColor, Color.WHITE);
a.recycle();
return color;
}
private static boolean getRaisedStatusFromAttributeSet(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ButtonCompat, 0, 0);
boolean raised = a.getBoolean(R.styleable.ButtonCompat_buttonRaised, true);
a.recycle();
return raised;
}
} }
// 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.
package org.chromium.ui.widget;
import android.annotation.TargetApi;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.RippleDrawable;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.Nullable;
import android.support.v4.graphics.ColorUtils;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.content.res.AppCompatResources;
import android.util.StateSet;
import android.view.View;
import org.chromium.ui.R;
/**
* A helper class to create and maintain a background drawable with customized background color,
* ripple color, and corner radius.
*/
class RippleBackgroundHelper {
private static final int[] STATE_SET_PRESSED = {android.R.attr.state_pressed};
private static final int[] STATE_SET_SELECTED = {android.R.attr.state_selected};
private static final int[] STATE_SET_SELECTED_PRESSED = {
android.R.attr.state_selected, android.R.attr.state_pressed};
private final View mView;
private @Nullable ColorStateList mBackgroundColorList;
private GradientDrawable mBackgroundGradient;
// Used for applying tint on pre-L versions.
private Drawable mBackgroundDrawablePreL;
private Drawable mRippleDrawablePreL;
/**
* @param view The {@link View} on which background will be applied.
* @param backgroundColorResId The resource id of the background color.
* @param rippleColorResId The resource id of the ripple color.
*/
RippleBackgroundHelper(
View view, @ColorRes int backgroundColorResId, @ColorRes int rippleColorResId) {
mView = view;
ColorStateList rippleColorList =
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) {
mBackgroundDrawablePreL = DrawableCompat.wrap(mBackgroundGradient);
GradientDrawable rippleGradient = new GradientDrawable();
rippleGradient.setCornerRadius(cornerRadius);
mRippleDrawablePreL = DrawableCompat.wrap(rippleGradient);
DrawableCompat.setTintList(mRippleDrawablePreL, rippleColorList);
wrappedDrawable = new LayerDrawable(
new Drawable[] {mBackgroundDrawablePreL, mRippleDrawablePreL});
} else {
GradientDrawable mask = new GradientDrawable();
mask.setCornerRadius(cornerRadius);
mask.setColor(Color.WHITE);
wrappedDrawable = new RippleDrawable(
convertToRippleDrawableColorList(rippleColorList), mBackgroundGradient, mask);
}
int paddingLeft = mView.getPaddingLeft();
int paddingTop = mView.getPaddingTop();
int paddingRight = mView.getPaddingRight();
int paddingBottom = mView.getPaddingBottom();
mView.setBackground(wrappedDrawable);
setBackgroundColor(backgroundColorList);
// On KitKat, setting the background on the view can cause padding reset. Save the padding
// and re-apply after background is set.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
mView.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
}
}
/**
* @param color The {@link ColorStateList} to be set as the background color on the background
* drawable.
*/
void setBackgroundColor(ColorStateList color) {
if (color == mBackgroundColorList) return;
mBackgroundColorList = color;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
DrawableCompat.setTintList(mBackgroundDrawablePreL, color);
} else {
mBackgroundGradient.setColor(color);
}
}
/**
* Called from the view when drawable state is changed to update the state of the background
* color and the ripple color for pre-L versions.
*/
void onDrawableStateChanged() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) return;
int[] state = mView.getDrawableState();
mBackgroundDrawablePreL.setState(state);
mRippleDrawablePreL.setState(state);
}
/**
* @return The color under the specified states in the specified {@link ColorStateList}.
*/
private static @ColorInt int getColorForState(ColorStateList colorStateList, int[] states) {
return colorStateList.getColorForState(states, colorStateList.getDefaultColor());
}
/**
* Adjusts the opacity of the ripple color since {@link RippleDrawable} uses about 50% opacity
* of color for ripple effect.
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private @ColorInt static int doubleAlpha(@ColorInt int color) {
int alpha = Math.min(Color.alpha(color) * 2, 255);
return ColorUtils.setAlphaComponent(color, alpha);
}
/**
* Converts the specified {@link ColorStateList} to one that can be applied to a
* {@link RippleDrawable}.
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static ColorStateList convertToRippleDrawableColorList(ColorStateList colorStateList) {
return new ColorStateList(new int[][] {STATE_SET_SELECTED, StateSet.NOTHING},
new int[] {
doubleAlpha(getColorForState(colorStateList, STATE_SET_SELECTED_PRESSED)),
doubleAlpha(getColorForState(colorStateList, STATE_SET_PRESSED))});
}
}
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