diff --git a/lib/java/com/google/android/material/button/MaterialButton.java b/lib/java/com/google/android/material/button/MaterialButton.java
index 962c76b33e6..a3595d77ef9 100644
--- a/lib/java/com/google/android/material/button/MaterialButton.java
+++ b/lib/java/com/google/android/material/button/MaterialButton.java
@@ -1212,11 +1212,33 @@ public void toggle() {
@Override
public boolean performClick() {
- toggle();
+ if (materialButtonHelper.isToggleCheckedStateOnClick()) {
+ toggle();
+ }
return super.performClick();
}
+ /**
+ * Returns whether or not clicking the button will toggle the checked state.
+ *
+ * @see #setToggleCheckedStateOnClick(boolean)
+ * @attr ref R.styleable#toggleCheckedStateOnClick
+ */
+ public boolean isToggleCheckedStateOnClick() {
+ return materialButtonHelper.isToggleCheckedStateOnClick();
+ }
+
+ /**
+ * Sets whether or not to toggle the button checked state on click.
+ *
+ * @param toggleCheckedStateOnClick whether or not to toggle the checked state on click.
+ * @attr ref R.styleable#toggleCheckedStateOnClick
+ */
+ public void setToggleCheckedStateOnClick(boolean toggleCheckedStateOnClick) {
+ materialButtonHelper.setToggleCheckedStateOnClick(toggleCheckedStateOnClick);
+ }
+
/**
* Returns whether this MaterialButton is checkable.
*
diff --git a/lib/java/com/google/android/material/button/MaterialButtonHelper.java b/lib/java/com/google/android/material/button/MaterialButtonHelper.java
index da666c735d4..0fea6158aeb 100644
--- a/lib/java/com/google/android/material/button/MaterialButtonHelper.java
+++ b/lib/java/com/google/android/material/button/MaterialButtonHelper.java
@@ -76,6 +76,7 @@ class MaterialButtonHelper {
private boolean backgroundOverwritten = false;
private boolean cornerRadiusSet = false;
private boolean checkable;
+ private boolean toggleCheckedStateOnClick = true;
private LayerDrawable rippleDrawable;
private int elevation;
@@ -117,6 +118,9 @@ void loadFromAttributes(@NonNull TypedArray attributes) {
checkable = attributes.getBoolean(R.styleable.MaterialButton_android_checkable, false);
elevation = attributes.getDimensionPixelSize(R.styleable.MaterialButton_elevation, 0);
+ toggleCheckedStateOnClick =
+ attributes.getBoolean(R.styleable.MaterialButton_toggleCheckedStateOnClick, true);
+
// Store padding before setting background, since background overwrites padding values
int paddingStart = ViewCompat.getPaddingStart(materialButton);
int paddingTop = materialButton.getPaddingTop();
@@ -362,6 +366,14 @@ boolean isCheckable() {
return checkable;
}
+ boolean isToggleCheckedStateOnClick() {
+ return toggleCheckedStateOnClick;
+ }
+
+ void setToggleCheckedStateOnClick(boolean toggleCheckedStateOnClick) {
+ this.toggleCheckedStateOnClick = toggleCheckedStateOnClick;
+ }
+
@Nullable
private MaterialShapeDrawable getSurfaceColorStrokeDrawable() {
return getMaterialShapeDrawable(true);
diff --git a/lib/java/com/google/android/material/button/res-public/values/public.xml b/lib/java/com/google/android/material/button/res-public/values/public.xml
index 6f2eeb4d3bf..60b648b2132 100644
--- a/lib/java/com/google/android/material/button/res-public/values/public.xml
+++ b/lib/java/com/google/android/material/button/res-public/values/public.xml
@@ -25,6 +25,7 @@
+
diff --git a/lib/java/com/google/android/material/button/res/values/attrs.xml b/lib/java/com/google/android/material/button/res/values/attrs.xml
index 031e1a85a4d..c7c00919a3d 100644
--- a/lib/java/com/google/android/material/button/res/values/attrs.xml
+++ b/lib/java/com/google/android/material/button/res/values/attrs.xml
@@ -97,6 +97,8 @@
+
+
diff --git a/lib/javatests/com/google/android/material/button/MaterialButtonTest.java b/lib/javatests/com/google/android/material/button/MaterialButtonTest.java
index d8107d06747..f3cf1efb24c 100644
--- a/lib/javatests/com/google/android/material/button/MaterialButtonTest.java
+++ b/lib/javatests/com/google/android/material/button/MaterialButtonTest.java
@@ -148,6 +148,40 @@ public void setIcon_iconUpdated_whenCalledTwice() {
assertThat(unwrapDrawable).isEqualTo(drawable2);
}
+ @Test
+ public void checkedStateTogglesOnClick() {
+ MaterialButton materialButton = new MaterialButton(context);
+ materialButton.setCheckable(true);
+
+ materialButton.performClick();
+ assertThat(materialButton.isChecked()).isTrue();
+
+ materialButton.performClick();
+ assertThat(materialButton.isChecked()).isFalse();
+ }
+
+ @Test
+ public void togglingCheckedStateTogglesOnClick() {
+ MaterialButton materialButton = new MaterialButton(context);
+ materialButton.setCheckable(true);
+ assertThat(materialButton.isChecked()).isFalse();
+
+ materialButton.setToggleCheckedStateOnClick(false);
+ materialButton.performClick();
+ assertThat(materialButton.isChecked()).isFalse();
+ }
+
+ @Test
+ public void setToggleCheckedStateOnClick() {
+ MaterialButton materialButton = new MaterialButton(context);
+ materialButton.setCheckable(true);
+
+ assertThat(materialButton.isToggleCheckedStateOnClick()).isTrue();
+
+ materialButton.setToggleCheckedStateOnClick(false);
+ assertThat(materialButton.isToggleCheckedStateOnClick()).isFalse();
+ }
+
@Test
@Config(minSdk = 23, maxSdk = 28)
public void setIcon_iconNotUpdated_whenPositionChanged() {