3232import androidx .appcompat .widget .TintTypedArray ;
3333import android .util .AttributeSet ;
3434import androidx .annotation .DrawableRes ;
35+ import androidx .annotation .IntDef ;
3536import androidx .annotation .NonNull ;
3637import androidx .annotation .Nullable ;
3738import androidx .annotation .Px ;
39+ import java .lang .annotation .Retention ;
40+ import java .lang .annotation .RetentionPolicy ;
3841import com .google .android .material .drawable .DrawableUtils ;
3942import com .google .android .material .focus .FocusRingDrawable ;
4043import com .google .android .material .internal .ThemeEnforcement ;
@@ -54,9 +57,51 @@ public class MaterialSwitch extends SwitchCompat {
5457 private static final int DEF_STYLE_RES = R .style .Widget_Material3_CompoundButton_MaterialSwitch ;
5558 private static final int [] STATE_SET_WITH_ICON = { R .attr .state_with_icon };
5659
60+ @ IntDef ({
61+ THUMB_ICON_VISIBILITY_ALWAYS ,
62+ THUMB_ICON_VISIBILITY_WHEN_CHECKED ,
63+ THUMB_ICON_VISIBILITY_WHEN_UNCHECKED ,
64+ THUMB_ICON_VISIBILITY_NEVER
65+ })
66+ @ Retention (RetentionPolicy .SOURCE )
67+ public @interface ThumbIconVisibility {}
68+
69+ /**
70+ * The thumb icon is displayed in both the checked and unchecked states.
71+ *
72+ * @see #setThumbIconVisibility(int)
73+ * @see #getThumbIconVisibility()
74+ */
75+ public static final int THUMB_ICON_VISIBILITY_ALWAYS = 0 ;
76+
77+ /**
78+ * The thumb icon is displayed only in the checked state.
79+ *
80+ * @see #setThumbIconVisibility(int)
81+ * @see #getThumbIconVisibility()
82+ */
83+ public static final int THUMB_ICON_VISIBILITY_WHEN_CHECKED = 1 ;
84+
85+ /**
86+ * The thumb icon is displayed only in the unchecked state.
87+ *
88+ * @see #setThumbIconVisibility(int)
89+ * @see #getThumbIconVisibility()
90+ */
91+ public static final int THUMB_ICON_VISIBILITY_WHEN_UNCHECKED = 2 ;
92+
93+ /**
94+ * The thumb icon is never displayed.
95+ *
96+ * @see #setThumbIconVisibility(int)
97+ * @see #getThumbIconVisibility()
98+ */
99+ public static final int THUMB_ICON_VISIBILITY_NEVER = 3 ;
100+
57101 @ Nullable private Drawable thumbDrawable ;
58102 @ Nullable private Drawable thumbIconDrawable ;
59- @ Px private int thumbIconSize = DrawableUtils .INTRINSIC_SIZE ;
103+ @ Px private int thumbIconSize ;
104+ @ ThumbIconVisibility private int thumbIconVisibility ;
60105
61106 @ Nullable private Drawable trackDrawable ;
62107 @ Nullable private Drawable trackDecorationDrawable ;
@@ -99,6 +144,8 @@ public MaterialSwitch(@NonNull Context context, @Nullable AttributeSet attrs, in
99144 thumbIconDrawable = attributes .getDrawable (R .styleable .MaterialSwitch_thumbIcon );
100145 thumbIconSize = attributes .getDimensionPixelSize (
101146 R .styleable .MaterialSwitch_thumbIconSize , DrawableUtils .INTRINSIC_SIZE );
147+ thumbIconVisibility = attributes .getInt (
148+ R .styleable .MaterialSwitch_thumbIconVisibility , THUMB_ICON_VISIBILITY_ALWAYS );
102149
103150 thumbIconTintList = attributes .getColorStateList (R .styleable .MaterialSwitch_thumbIconTint );
104151 thumbIconTintMode =
@@ -142,10 +189,12 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
142189
143190 @ Override
144191 protected int [] onCreateDrawableState (int extraSpace ) {
145- int [] drawableState = super . onCreateDrawableState ( extraSpace + 1 ) ;
146-
147- if ( thumbIconDrawable != null ) {
192+ final int [] drawableState ;
193+ if ( shouldShowThumbIcon ()) {
194+ drawableState = super . onCreateDrawableState ( extraSpace + 1 );
148195 mergeDrawableStates (drawableState , STATE_SET_WITH_ICON );
196+ } else {
197+ drawableState = super .onCreateDrawableState (extraSpace );
149198 }
150199
151200 currentStateUnchecked = DrawableUtils .getUncheckedState (drawableState );
@@ -154,6 +203,36 @@ protected int[] onCreateDrawableState(int extraSpace) {
154203 return drawableState ;
155204 }
156205
206+ private boolean shouldShowThumbIcon () {
207+ if (thumbIconDrawable == null ) {
208+ return false ;
209+ }
210+
211+ switch (thumbIconVisibility ) {
212+ case THUMB_ICON_VISIBILITY_ALWAYS :
213+ return true ;
214+ case THUMB_ICON_VISIBILITY_WHEN_CHECKED :
215+ return isChecked ();
216+ case THUMB_ICON_VISIBILITY_WHEN_UNCHECKED :
217+ return !isChecked ();
218+ case THUMB_ICON_VISIBILITY_NEVER :
219+ return false ;
220+ default :
221+ throw new IllegalArgumentException ("Unexpected thumbIconVisibility: " + thumbIconVisibility );
222+ }
223+ }
224+
225+ @ Override
226+ public void setChecked (boolean checked ) {
227+ boolean oldState = shouldShowThumbIcon ();
228+ super .setChecked (checked );
229+ boolean newState = shouldShowThumbIcon ();
230+
231+ if (oldState != newState ) {
232+ refreshThumbDrawable ();
233+ }
234+ }
235+
157236 @ Override
158237 public void setThumbDrawable (@ Nullable Drawable drawable ) {
159238 thumbDrawable = drawable ;
@@ -290,6 +369,32 @@ public PorterDuff.Mode getThumbIconTintMode() {
290369 return thumbIconTintMode ;
291370 }
292371
372+ /**
373+ * Sets the checked state(s) in which the thumb icon will be displayed. The default value is
374+ * {@link #THUMB_ICON_VISIBILITY_ALWAYS}.
375+ *
376+ * @param thumbIconVisibility one of {@link #THUMB_ICON_VISIBILITY_ALWAYS},
377+ * {@link #THUMB_ICON_VISIBILITY_WHEN_CHECKED}, {@link #THUMB_ICON_VISIBILITY_WHEN_UNCHECKED},
378+ * or {@link #THUMB_ICON_VISIBILITY_NEVER}
379+ * @attr ref com.google.android.material.R.styleable#MaterialSwitch_thumbIconVisibility
380+ */
381+ public void setThumbIconVisibility (@ ThumbIconVisibility int thumbIconVisibility ) {
382+ if (this .thumbIconVisibility != thumbIconVisibility ) {
383+ this .thumbIconVisibility = thumbIconVisibility ;
384+ refreshThumbDrawable ();
385+ }
386+ }
387+
388+ /**
389+ * Returns the checked state(s) in which the thumb icon is displayed.
390+ *
391+ * @attr ref com.google.android.material.R.styleable#MaterialSwitch_thumbIconVisibility
392+ */
393+ @ ThumbIconVisibility
394+ public int getThumbIconVisibility () {
395+ return thumbIconVisibility ;
396+ }
397+
293398 @ Override
294399 public void setTrackDrawable (@ Nullable Drawable track ) {
295400 trackDrawable = track ;
@@ -414,8 +519,9 @@ private void refreshThumbDrawable() {
414519
415520 updateDrawableTints ();
416521
522+ Drawable effectiveThumbIconDrawable = shouldShowThumbIcon () ? thumbIconDrawable : null ;
417523 super .setThumbDrawable (DrawableUtils .compositeTwoLayeredDrawable (
418- thumbDrawable , thumbIconDrawable , thumbIconSize , thumbIconSize ));
524+ thumbDrawable , effectiveThumbIconDrawable , thumbIconSize , thumbIconSize ));
419525
420526 refreshDrawableState ();
421527 }
0 commit comments