Skip to content

Commit 8f4837e

Browse files
committed
[MaterialCheckBox] Horizontally center the checkbox button drawable if there is no text
PiperOrigin-RevId: 421304994
1 parent 90787bf commit 8f4837e

File tree

8 files changed

+99
-49
lines changed

8 files changed

+99
-49
lines changed

catalog/java/io/material/catalog/checkbox/CheckBoxMainDemoFragment.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,8 @@ public class CheckBoxMainDemoFragment extends DemoFragment {
3636
public View onCreateDemoView(
3737
LayoutInflater layoutInflater, @Nullable ViewGroup viewGroup, @Nullable Bundle bundle) {
3838
View view = layoutInflater.inflate(R.layout.cat_checkbox, viewGroup, false /* attachToRoot */);
39-
ViewGroup checkBoxDemoViewGroup = view.findViewById(R.id.main_viewGroup);
40-
View toggledView =
41-
layoutInflater.inflate(R.layout.cat_checkbox_toggled, checkBoxDemoViewGroup, false);
42-
checkBoxDemoViewGroup.addView(toggledView);
43-
List<CheckBox> toggledCheckBoxes =
44-
DemoUtils.<CheckBox>findViewsWithType(toggledView, CheckBox.class);
39+
ViewGroup toggleContainer = view.findViewById(R.id.checkbox_toggle_container);
40+
List<CheckBox> toggledCheckBoxes = DemoUtils.findViewsWithType(toggleContainer, CheckBox.class);
4541

4642
CheckBox checkBoxToggle = view.findViewById(R.id.checkbox_toggle);
4743
checkBoxToggle.setOnCheckedChangeListener(

catalog/java/io/material/catalog/checkbox/res/layout/cat_checkbox.xml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,37 @@
8080
android:enabled="true"
8181
android:text="@string/cat_checkbox_enablable_description"
8282
android:textSize="@dimen/cat_checkbox_header_size"/>
83+
<LinearLayout
84+
android:id="@+id/checkbox_toggle_container"
85+
android:layout_width="match_parent"
86+
android:layout_height="wrap_content"
87+
android:layout_marginStart="@dimen/cat_checkbox_indent"
88+
android:orientation="vertical">
89+
<CheckBox
90+
android:layout_width="match_parent"
91+
android:layout_height="match_parent"
92+
android:checked="true"
93+
android:enabled="false"
94+
android:text="@string/cat_checkbox_toggle"/>
95+
<CheckBox
96+
android:layout_width="match_parent"
97+
android:layout_height="match_parent"
98+
android:checked="false"
99+
android:enabled="false"
100+
android:text="@string/cat_checkbox_toggle"/>
101+
</LinearLayout>
102+
<ImageView
103+
android:layout_width="match_parent"
104+
android:layout_height="@dimen/cat_checkbox_line_separator_thickness"
105+
android:layout_marginTop="@dimen/cat_checkbox_line_separator_margin"
106+
android:layout_marginBottom="@dimen/cat_checkbox_line_separator_margin"
107+
android:background="?attr/colorSecondary"/>
108+
<TextView
109+
android:layout_width="match_parent"
110+
android:layout_height="wrap_content"
111+
android:text="@string/cat_checkbox_no_text"
112+
android:textSize="@dimen/cat_checkbox_header_size"/>
113+
<CheckBox
114+
android:layout_width="wrap_content"
115+
android:layout_height="wrap_content"/>
83116
</LinearLayout>

catalog/java/io/material/catalog/checkbox/res/layout/cat_checkbox_toggled.xml

Lines changed: 0 additions & 38 deletions
This file was deleted.

catalog/java/io/material/catalog/checkbox/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@
2626
<string name="cat_checkbox_disabled">Disabled</string>
2727
<string name="cat_checkbox_enablable_description">Check this checkbox to control the enabled state of the boxes below.</string>
2828
<string name="cat_checkbox_toggle">Controlled by a checkbox</string>
29+
<string name="cat_checkbox_no_text">Below is a checkbox with no text.</string>
2930
</resources>

docs/components/Checkbox.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,12 @@ checkbox.setOnCheckedChangeListener { buttonView, isChecked
113113

114114
### Checkbox attributes
115115

116-
Element | Attribute | Related method(s) | Default value
117-
-------------------------- | ------------------------------------------ | ---------------------------------------------------------- | -------------
118-
**To use material colors** | `app:useMaterialThemeColors` | `setUseMaterialThemeColors`<br/>`isUseMaterialThemeColors` | `true` (ignored if `app:buttonTint` is set)
119-
**Color** | `app:buttonTint` | `setButtonTintList`<br/>`getButtonTintList` | `?attr/colorOnSurface` (see all [states](https://github.com/material-components/material-components-android/tree/master/lib/java/com/google/android/material/color/res/color/m3_selection_control_button_tint.xml))
120-
**Min size** | `android:minWidth`<br/>`android:minHeight` | `(set/get)MinWidth`<br/>`(set/get)MinHeight` | `?attr/minTouchTargetSize`
116+
Element | Attribute | Related method(s) | Default value
117+
-------------------------- | ------------------------------------------ | ---------------------------------------------------------- | -------------
118+
**To use material colors** | `app:useMaterialThemeColors` | `setUseMaterialThemeColors`<br/>`isUseMaterialThemeColors` | `true` (ignored if `app:buttonTint` is set)
119+
**Color** | `app:buttonTint` | `setButtonTintList`<br/>`getButtonTintList` | `?attr/colorOnSurface` (see all [states](https://github.com/material-components/material-components-android/tree/master/lib/java/com/google/android/material/color/res/color/m3_selection_control_button_tint.xml))
120+
**Min size** | `android:minWidth`<br/>`android:minHeight` | `(set/get)MinWidth`<br/>`(set/get)MinHeight` | `?attr/minTouchTargetSize`
121+
**Centered icon if no text** | `app:centerIfNoTextEnabled` | `setCenterIfNoTextEnabled`<br/>`isCenterIfNoTextEnabled` | `true`
121122

122123
The color of the checkbox defaults to `?attr/colorOnSurface` (unchecked) and
123124
`?attr/colorPrimary` (checked) defined in your app theme. If you want to

lib/java/com/google/android/material/checkbox/MaterialCheckBox.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,18 @@
2323
import android.content.Context;
2424
import android.content.res.ColorStateList;
2525
import android.content.res.TypedArray;
26+
import android.graphics.Canvas;
27+
import android.graphics.Rect;
28+
import android.graphics.drawable.Drawable;
2629
import androidx.appcompat.widget.AppCompatCheckBox;
30+
import android.text.TextUtils;
2731
import android.util.AttributeSet;
2832
import androidx.annotation.Nullable;
33+
import androidx.core.graphics.drawable.DrawableCompat;
2934
import androidx.core.widget.CompoundButtonCompat;
3035
import com.google.android.material.color.MaterialColors;
3136
import com.google.android.material.internal.ThemeEnforcement;
37+
import com.google.android.material.internal.ViewUtils;
3238
import com.google.android.material.resources.MaterialResources;
3339

3440
/**
@@ -52,6 +58,7 @@ public class MaterialCheckBox extends AppCompatCheckBox {
5258
};
5359
@Nullable private ColorStateList materialThemeColorsTintList;
5460
private boolean useMaterialThemeColors;
61+
private boolean centerIfNoTextEnabled;
5562

5663
public MaterialCheckBox(Context context) {
5764
this(context, null);
@@ -81,10 +88,39 @@ public MaterialCheckBox(Context context, @Nullable AttributeSet attrs, int defSt
8188

8289
useMaterialThemeColors =
8390
attributes.getBoolean(R.styleable.MaterialCheckBox_useMaterialThemeColors, false);
91+
centerIfNoTextEnabled =
92+
attributes.getBoolean(R.styleable.MaterialCheckBox_centerIfNoTextEnabled, true);
8493

8594
attributes.recycle();
8695
}
8796

97+
@Override
98+
protected void onDraw(Canvas canvas) {
99+
// Horizontally center the button drawable and ripple when there's no text.
100+
if (centerIfNoTextEnabled && TextUtils.isEmpty(getText())) {
101+
Drawable drawable = CompoundButtonCompat.getButtonDrawable(this);
102+
if (drawable != null) {
103+
int direction = ViewUtils.isLayoutRtl(this) ? -1 : 1;
104+
int dx = (getWidth() - drawable.getIntrinsicWidth()) / 2 * direction;
105+
106+
int saveCount = canvas.save();
107+
canvas.translate(dx, 0);
108+
super.onDraw(canvas);
109+
canvas.restoreToCount(saveCount);
110+
111+
if (getBackground() != null) {
112+
Rect bounds = drawable.getBounds();
113+
DrawableCompat.setHotspotBounds(
114+
getBackground(), bounds.left + dx, bounds.top, bounds.right + dx, bounds.bottom);
115+
}
116+
117+
return;
118+
}
119+
}
120+
121+
super.onDraw(canvas);
122+
}
123+
88124
@Override
89125
protected void onAttachedToWindow() {
90126
super.onAttachedToWindow();
@@ -113,6 +149,22 @@ public boolean isUseMaterialThemeColors() {
113149
return useMaterialThemeColors;
114150
}
115151

152+
/**
153+
* Sets whether this {@link MaterialCheckBox} should center the checkbox icon when there is no
154+
* text. Default is true.
155+
*/
156+
public void setCenterIfNoTextEnabled(boolean centerIfNoTextEnabled) {
157+
this.centerIfNoTextEnabled = centerIfNoTextEnabled;
158+
}
159+
160+
/**
161+
* Returns true if this {@link MaterialCheckBox} will center the checkbox icon when there is no
162+
* text.
163+
*/
164+
public boolean isCenterIfNoTextEnabled() {
165+
return centerIfNoTextEnabled;
166+
}
167+
116168
private ColorStateList getMaterialThemeColorsTintList() {
117169
if (materialThemeColorsTintList == null) {
118170
int[] checkBoxColorsList = new int[ENABLED_CHECKED_STATES.length];

lib/java/com/google/android/material/checkbox/res-public/values/public.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,6 @@
1818
<!-- Definitions of attributes to be exposed as public -->
1919
<resources>
2020
<public name="Widget.Material3.CompoundButton.CheckBox" type="style"/>
21+
22+
<public name="centerIfNoTextEnabled" type="attr"/>
2123
</resources>

lib/java/com/google/android/material/checkbox/res/values/attrs.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,8 @@
2323
<attr name="useMaterialThemeColors"/>
2424
<!-- Tint for the checkbox. -->
2525
<attr name="buttonTint"/>
26+
<!-- Whether the MaterialCheckBox button drawable (checkbox icon) will be
27+
centered when there is no text set for the checkbox. Default is true. -->
28+
<attr name="centerIfNoTextEnabled" format="boolean"/>
2629
</declare-styleable>
2730
</resources>

0 commit comments

Comments
 (0)