Skip to content

Commit fd40fea

Browse files
committed
[Switch] Override switch width set by AppCompat to respect the drawable width
PiperOrigin-RevId: 449238028
1 parent 413a047 commit fd40fea

File tree

53 files changed

+146
-52
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+146
-52
lines changed

lib/java/com/google/android/material/materialswitch/MaterialSwitch.java

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import static com.google.android.material.theme.overlay.MaterialThemeOverlay.wrap;
2222

23+
import android.annotation.SuppressLint;
2324
import android.content.Context;
2425
import android.content.res.ColorStateList;
2526
import android.graphics.PorterDuff;
@@ -36,6 +37,8 @@
3637
import androidx.annotation.Nullable;
3738
import androidx.core.graphics.drawable.DrawableCompat;
3839
import com.google.android.material.internal.ThemeEnforcement;
40+
import com.google.android.material.internal.ViewUtils;
41+
import java.lang.reflect.Field;
3942

4043
/**
4144
* A class that creates a Material Themed Switch. This class is intended to provide a brand new
@@ -45,6 +48,8 @@
4548
public class MaterialSwitch extends SwitchCompat {
4649
private static final int DEF_STYLE_RES = R.style.Widget_Material3_CompoundButton_MaterialSwitch;
4750

51+
@NonNull private final SwitchWidth switchWidth = SwitchWidth.create(this);
52+
4853
@Nullable private Drawable trackDrawable;
4954
@Nullable private Drawable trackDecorationDrawable;
5055

@@ -86,6 +91,40 @@ public MaterialSwitch(@NonNull Context context, @Nullable AttributeSet attrs, in
8691
refreshTrackDrawable();
8792
}
8893

94+
// TODO(b/227338106): remove this workaround and move to use setEnforceSwitchWidth(false) after
95+
// AppCompat 1.6.0-stable is released.
96+
@Override
97+
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
98+
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
99+
switchWidth.set(getSwitchMinWidth());
100+
}
101+
102+
// TODO(b/227338106): remove this workaround and move to use setEnforceSwitchWidth(false) after
103+
// AppCompat 1.6.0-stable is released.
104+
@Override
105+
public int getCompoundPaddingLeft() {
106+
if (!ViewUtils.isLayoutRtl(this)) {
107+
return super.getCompoundPaddingLeft();
108+
}
109+
// Compound paddings are used during onMeasure() to decide the component width, at that time
110+
// the switch width is not overridden yet so we need to adjust the value to make measurement
111+
// right. This can be removed after the workaround is removed.
112+
return super.getCompoundPaddingLeft() - switchWidth.get() + getSwitchMinWidth();
113+
}
114+
115+
// TODO(b/227338106): remove this workaround and move to use setEnforceSwitchWidth(false) after
116+
// AppCompat 1.6.0-stable is released.
117+
@Override
118+
public int getCompoundPaddingRight() {
119+
if (ViewUtils.isLayoutRtl(this)) {
120+
return super.getCompoundPaddingRight();
121+
}
122+
// Compound paddings are used during onMeasure() to decide the component width, at that time
123+
// the switch width is not overridden yet so we need to adjust the value to make measurement
124+
// right. This can be removed after the workaround is removed.
125+
return super.getCompoundPaddingRight() - switchWidth.get() + getSwitchMinWidth();
126+
}
127+
89128
@Override
90129
public void setTrackDrawable(@Nullable Drawable track) {
91130
trackDrawable = track;
@@ -214,6 +253,9 @@ private void refreshTrackDrawable() {
214253
} else {
215254
finalTrackDrawable = trackDecorationDrawable;
216255
}
256+
if (finalTrackDrawable != null) {
257+
setSwitchMinWidth(finalTrackDrawable.getIntrinsicWidth());
258+
}
217259
super.setTrackDrawable(finalTrackDrawable);
218260
}
219261

@@ -231,4 +273,56 @@ private static Drawable setDrawableTintListIfNeeded(
231273
}
232274
return drawable;
233275
}
276+
277+
// TODO(b/227338106): remove this workaround and move to use setEnforceSwitchWidth(false) after
278+
// AppCompat 1.6.0-stable is released.
279+
@SuppressLint("PrivateApi")
280+
private static final class SwitchWidth {
281+
282+
@NonNull private final MaterialSwitch materialSwitch;
283+
@Nullable private final Field switchWidthField;
284+
285+
@NonNull
286+
static SwitchWidth create(@NonNull MaterialSwitch materialSwitch) {
287+
return new SwitchWidth(materialSwitch, createSwitchWidthField());
288+
}
289+
290+
private SwitchWidth(@NonNull MaterialSwitch materialSwitch, @Nullable Field switchWidthField) {
291+
this.materialSwitch = materialSwitch;
292+
this.switchWidthField = switchWidthField;
293+
}
294+
295+
int get() {
296+
try {
297+
if (switchWidthField != null) {
298+
return switchWidthField.getInt(materialSwitch);
299+
}
300+
} catch (IllegalAccessException e) {
301+
// Fall through
302+
}
303+
// Return getSwitchMinWidth() so no width adjustment will be done.
304+
return materialSwitch.getSwitchMinWidth();
305+
}
306+
307+
void set(int switchWidth) {
308+
try {
309+
if (switchWidthField != null) {
310+
switchWidthField.setInt(materialSwitch, switchWidth);
311+
}
312+
} catch (IllegalAccessException e) {
313+
// Fall through
314+
}
315+
}
316+
317+
@Nullable
318+
private static Field createSwitchWidthField() {
319+
try {
320+
Field switchWidthField = SwitchCompat.class.getDeclaredField("mSwitchWidth");
321+
switchWidthField.setAccessible(true);
322+
return switchWidthField;
323+
} catch (NoSuchFieldException | SecurityException e) {
324+
return null;
325+
}
326+
}
327+
}
234328
}

lib/javatests/com/google/android/material/appbar/MaterialToolbarTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
package com.google.android.material.appbar;
1717

18-
import com.google.android.material.R;
18+
import com.google.android.material.test.R;
1919

2020
import static com.google.common.truth.Truth.assertThat;
2121

lib/javatests/com/google/android/material/badge/BadgeDrawableTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
package com.google.android.material.badge;
1717

18-
import com.google.android.material.R;
18+
import com.google.android.material.test.R;
1919

2020
import static com.google.common.truth.Truth.assertThat;
2121

lib/javatests/com/google/android/material/badge/BadgeUtilsTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
package com.google.android.material.badge;
1717

18-
import com.google.android.material.R;
18+
import com.google.android.material.test.R;
1919

2020
import static com.google.common.truth.Truth.assertThat;
2121

lib/javatests/com/google/android/material/bottomnavigation/BottomNavigationViewTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
package com.google.android.material.bottomnavigation;
1717

18-
import com.google.android.material.R;
18+
import com.google.android.material.test.R;
1919

2020
import static com.google.common.truth.Truth.assertThat;
2121

lib/javatests/com/google/android/material/bottomsheet/BottomSheetBehaviorTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
package com.google.android.material.bottomsheet;
1717

18-
import com.google.android.material.R;
18+
import com.google.android.material.test.R;
1919

2020
import static com.google.common.truth.Truth.assertThat;
2121

lib/javatests/com/google/android/material/button/MaterialButtonTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
package com.google.android.material.button;
1717

18-
import com.google.android.material.R;
18+
import com.google.android.material.test.R;
1919

2020
import static com.google.common.truth.Truth.assertThat;
2121

lib/javatests/com/google/android/material/button/MaterialButtonToggleGroupTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package com.google.android.material.button;
1818

19-
import com.google.android.material.R;
19+
import com.google.android.material.test.R;
2020

2121
import static android.view.View.GONE;
2222
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;

lib/javatests/com/google/android/material/checkbox/MaterialCheckBoxTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package com.google.android.material.checkbox;
1818

19-
import com.google.android.material.R;
19+
import com.google.android.material.test.R;
2020

2121
import static com.google.common.truth.Truth.assertThat;
2222

lib/javatests/com/google/android/material/chip/ChipGroupTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616
package com.google.android.material.chip;
1717

18-
import com.google.android.material.R;
18+
import com.google.android.material.test.R;
1919

2020
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
2121
import static com.google.common.truth.Truth.assertThat;

0 commit comments

Comments
 (0)