Skip to content

Commit 3abb658

Browse files
paulfthomasdsn5ft
authored andcommitted
[MaterialSwitch] Amendments to thumb icon size support
Resolves #3364 PiperOrigin-RevId: 549627031 (cherry picked from commit db9a641)
1 parent 0c0addd commit 3abb658

File tree

11 files changed

+160
-102
lines changed

11 files changed

+160
-102
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!--
2+
~ Copyright (C) 2023 The Android Open Source Project
3+
~
4+
~ Licensed under the Apache License, Version 2.0 (the "License");
5+
~ you may not use this file except in compliance with the License.
6+
~ You may obtain a copy of the License at
7+
~
8+
~ http://www.apache.org/licenses/LICENSE-2.0
9+
~
10+
~ Unless required by applicable law or agreed to in writing, software
11+
~ distributed under the License is distributed on an "AS IS" BASIS,
12+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
~ See the License for the specific language governing permissions and
14+
~ limitations under the License.
15+
-->
16+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
17+
xmlns:tools="http://schemas.android.com/tools"
18+
android:width="48dp"
19+
android:height="48dp"
20+
android:tint="?attr/colorControlNormal"
21+
android:viewportHeight="960"
22+
android:viewportWidth="960"
23+
tools:ignore="NewApi">
24+
<path
25+
android:fillColor="@android:color/white"
26+
android:pathData="M378,714L154,490L197,447L378,628L762,244L805,287L378,714Z" />
27+
</vector>

catalog/java/io/material/catalog/materialswitch/res/layout/cat_material_switch.xml

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
limitations under the License.
1717
-->
1818

19-
<ScrollView
20-
xmlns:android="http://schemas.android.com/apk/res/android"
19+
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
2120
android:layout_width="match_parent"
22-
android:layout_height="match_parent">
21+
android:layout_height="match_parent"
22+
xmlns:app="http://schemas.android.com/apk/res-auto">
2323

2424
<LinearLayout
2525
android:id="@+id/main_viewGroup"
@@ -75,6 +75,30 @@
7575
android:checked="false"
7676
android:enabled="false"
7777
android:text="@string/cat_switch_disabled" />
78+
79+
<TextView
80+
android:layout_width="match_parent"
81+
android:layout_height="match_parent"
82+
android:layout_columnSpan="2"
83+
android:text="@string/cat_switch_icon_guide"
84+
android:textSize="@dimen/cat_switch_header_size" />
85+
86+
<com.google.android.material.materialswitch.MaterialSwitch
87+
android:layout_width="match_parent"
88+
android:layout_height="match_parent"
89+
android:checked="true"
90+
android:enabled="true"
91+
app:thumbIcon="@drawable/mtrl_ic_check"
92+
android:text="@string/cat_switch_enabled" />
93+
94+
<com.google.android.material.materialswitch.MaterialSwitch
95+
android:layout_width="match_parent"
96+
android:layout_height="match_parent"
97+
android:checked="true"
98+
android:enabled="true"
99+
app:thumbIcon="@drawable/mtrl_ic_check"
100+
app:thumbIconSize="24dp"
101+
android:text="@string/cat_switch_enabled" />
78102
</GridLayout>
79103

80104
<ImageView

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
description="The description of how switches look like when disabled. [CHAR LIMIT=NONE]">
3434
Switch elements that are disabled cannot be interacted with and will appear faded.
3535
</string>
36+
<string name="cat_switch_icon_guide"
37+
description="The description of how switches look like with icon. [CHAR LIMIT=NONE]">
38+
Switch elements with an icon, default size (16dp) and 24dp.
39+
</string>
3640
<string name="cat_switch_enabled"
3741
description="The label of enabled switches. [CHAR LIMIT=NONE]">
3842
Enabled

docs/components/Switch.md

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -148,15 +148,11 @@ You can add an optional icon to enhance the on/off indication of your custom
148148
switch by assigning `app:thumbIcon`. This icon will be centered and displayed on
149149
top of the thumb drawable.
150150

151-
Element | Attribute | Related method(s) | Default value
152-
---------- |-----------------------|---------------------------------------------------| -------------
153-
**Icon** | `app:thumbIcon` | `setThumbIconDrawable`<br/>`getThumbIconDrawable` | `null`
154-
**Width** | `app:thumbIconWidth` | `setThumbIconWidth`<br/>`getThumbIconWidth` | Intrinsic width
155-
**Height** | `app:thumbIconHeight` | `setThumbIconHeight`<br/>`getThumbIconHeight` | Intrinsic height
156-
**Color** | `app:thumbIconTint` | `setThumbIconTintList`<br/>`getThumbIconTintList` | `?attr/colorSurfaceVariant` (unchecked)<br/>`?attr/colorOnPrimaryContainer` (checked)
157-
158-
**Note:** Custom thumb icon width/height is supported only for API 23 and above.
159-
For API < 23, the intrinsic size of the thumb icon will always be used.
151+
Element | Attribute | Related method(s) | Default value
152+
--------- |---------------------|---------------------------------------------------| -------------
153+
**Icon** | `app:thumbIcon` | `setThumbIconDrawable`<br/>`getThumbIconDrawable` | `null`
154+
**Size** | `app:thumbIconSize` | `setThumbIconSize`<br/>`getThumbIconSize` | `16dp`
155+
**Color** | `app:thumbIconTint` | `setThumbIconTintList`<br/>`getThumbIconTintList` | `?attr/colorSurfaceVariant` (unchecked)<br/>`?attr/colorOnPrimaryContainer` (checked)
160156

161157
### Track attributes
162158

lib/java/com/google/android/material/drawable/DrawableUtils.java

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
import androidx.annotation.NonNull;
4343
import androidx.annotation.Nullable;
4444
import androidx.annotation.Px;
45-
import androidx.annotation.RequiresApi;
4645
import androidx.annotation.RestrictTo;
4746
import androidx.annotation.RestrictTo.Scope;
4847
import androidx.annotation.XmlRes;
@@ -64,7 +63,7 @@ public final class DrawableUtils {
6463

6564
/**
6665
* Indicates to use the intrinsic size of the {@link Drawable}.
67-
*
66+
*
6867
* <p>Used in {@link #compositeTwoLayeredDrawable(Drawable, Drawable, int, int)}.
6968
*/
7069
public static final int INTRINSIC_SIZE = -1;
@@ -211,7 +210,7 @@ private static Drawable createTintableMutatedDrawableIfNeeded(
211210
/**
212211
* Composites two drawables, returning a drawable instance of {@link LayerDrawable},
213212
* with the top layer centered.
214-
*
213+
*
215214
* <p>If any of the drawables is null, this method will return the other.
216215
*
217216
* @param bottomLayerDrawable the drawable to be on the bottom layer
@@ -221,35 +220,16 @@ private static Drawable createTintableMutatedDrawableIfNeeded(
221220
public static Drawable compositeTwoLayeredDrawable(
222221
@Nullable Drawable bottomLayerDrawable,
223222
@Nullable Drawable topLayerDrawable) {
224-
if (VERSION.SDK_INT >= VERSION_CODES.M) {
225-
return compositeTwoLayeredDrawable(
226-
bottomLayerDrawable, topLayerDrawable, INTRINSIC_SIZE, INTRINSIC_SIZE);
227-
}
228-
229-
if (bottomLayerDrawable == null) {
230-
return topLayerDrawable;
231-
}
232-
if (topLayerDrawable == null) {
233-
return bottomLayerDrawable;
234-
}
235-
LayerDrawable drawable =
236-
new LayerDrawable(new Drawable[] {bottomLayerDrawable, topLayerDrawable});
237-
int horizontalInset =
238-
max(bottomLayerDrawable.getIntrinsicWidth()
239-
- getTopLayerIntrinsicWidth(bottomLayerDrawable, topLayerDrawable), 0) / 2;
240-
int verticalInset =
241-
max(bottomLayerDrawable.getIntrinsicHeight()
242-
- getTopLayerIntrinsicHeight(bottomLayerDrawable, topLayerDrawable), 0) / 2;
243-
drawable.setLayerInset(1, horizontalInset, verticalInset, horizontalInset, verticalInset);
244-
return drawable;
223+
return compositeTwoLayeredDrawable(
224+
bottomLayerDrawable, topLayerDrawable, INTRINSIC_SIZE, INTRINSIC_SIZE);
245225
}
246226

247227
/**
248228
* Composites two drawables, returning a drawable instance of {@link LayerDrawable},
249229
* with the top layer centered to the bottom layer. The top layer will be scaled according to the
250230
* provided desired width/height and the size of the bottom layer so the top layer can fit in the
251231
* bottom layer and preserve its desired aspect ratio.
252-
*
232+
*
253233
* <p>If any of the drawables is null, this method will return the other.
254234
*
255235
* @param bottomLayerDrawable the drawable to be on the bottom layer
@@ -259,7 +239,6 @@ public static Drawable compositeTwoLayeredDrawable(
259239
* @param topLayerDesiredHeight top layer desired height in pixels, or {@link #INTRINSIC_SIZE} to
260240
* use the intrinsic height.
261241
*/
262-
@RequiresApi(VERSION_CODES.M)
263242
@Nullable
264243
public static Drawable compositeTwoLayeredDrawable(
265244
@Nullable Drawable bottomLayerDrawable,
@@ -272,8 +251,6 @@ public static Drawable compositeTwoLayeredDrawable(
272251
if (topLayerDrawable == null) {
273252
return bottomLayerDrawable;
274253
}
275-
LayerDrawable drawable =
276-
new LayerDrawable(new Drawable[] {bottomLayerDrawable, topLayerDrawable});
277254

278255
if (topLayerDesiredWidth == INTRINSIC_SIZE) {
279256
topLayerDesiredWidth = getTopLayerIntrinsicWidth(bottomLayerDrawable, topLayerDrawable);
@@ -308,23 +285,41 @@ public static Drawable compositeTwoLayeredDrawable(
308285
}
309286
}
310287

311-
drawable.setLayerSize(1, topLayerNewWidth, topLayerNewHeight);
312-
drawable.setLayerGravity(1, Gravity.CENTER);
288+
LayerDrawable drawable;
289+
if (VERSION.SDK_INT >= VERSION_CODES.M) {
290+
drawable = new LayerDrawable(new Drawable[] {bottomLayerDrawable, topLayerDrawable});
291+
292+
drawable.setLayerSize(1, topLayerNewWidth, topLayerNewHeight);
293+
drawable.setLayerGravity(1, Gravity.CENTER);
294+
} else {
295+
Drawable scaledTopLayerDrawable =
296+
new ScaledDrawableWrapper(topLayerDrawable, topLayerNewWidth, topLayerNewHeight)
297+
.getDrawable();
298+
299+
drawable = new LayerDrawable(new Drawable[] {bottomLayerDrawable, scaledTopLayerDrawable});
300+
301+
final int horizontalInset =
302+
max((bottomLayerDrawable.getIntrinsicWidth() - topLayerNewWidth) / 2, 0);
303+
final int verticalInset =
304+
max((bottomLayerDrawable.getIntrinsicHeight() - topLayerNewHeight) / 2, 0);
305+
drawable.setLayerInset(1, horizontalInset, verticalInset, horizontalInset, verticalInset);
306+
}
307+
313308
return drawable;
314309
}
315310

316311
private static int getTopLayerIntrinsicWidth(
317312
@NonNull Drawable bottomLayerDrawable, @NonNull Drawable topLayerDrawable) {
318313
int topLayerIntrinsicWidth = topLayerDrawable.getIntrinsicWidth();
319-
return topLayerIntrinsicWidth == UNSPECIFIED_WIDTH
320-
? bottomLayerDrawable.getIntrinsicWidth() : topLayerIntrinsicWidth;
314+
return topLayerIntrinsicWidth != UNSPECIFIED_WIDTH
315+
? topLayerIntrinsicWidth : bottomLayerDrawable.getIntrinsicWidth();
321316
}
322317

323318
private static int getTopLayerIntrinsicHeight(
324319
@NonNull Drawable bottomLayerDrawable, @NonNull Drawable topLayerDrawable) {
325320
int topLayerIntrinsicHeight = topLayerDrawable.getIntrinsicHeight();
326-
return topLayerIntrinsicHeight == UNSPECIFIED_HEIGHT
327-
? bottomLayerDrawable.getIntrinsicHeight() : topLayerIntrinsicHeight;
321+
return topLayerIntrinsicHeight != UNSPECIFIED_HEIGHT
322+
? topLayerIntrinsicHeight : bottomLayerDrawable.getIntrinsicHeight();
328323
}
329324

330325
/** Returns a new state that adds the checked state to the input state. */
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2023 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.android.material.drawable;
18+
19+
import android.graphics.drawable.Drawable;
20+
import androidx.appcompat.graphics.drawable.DrawableWrapperCompat;
21+
import androidx.annotation.NonNull;
22+
import androidx.annotation.RestrictTo;
23+
import androidx.annotation.RestrictTo.Scope;
24+
25+
/**
26+
* An extension of {@link DrawableWrapperCompat} that will take a given Drawable and scale it by the
27+
* specified width and height.
28+
*/
29+
@RestrictTo(Scope.LIBRARY_GROUP)
30+
public class ScaledDrawableWrapper extends DrawableWrapperCompat {
31+
private final int width;
32+
private final int height;
33+
34+
public ScaledDrawableWrapper(@NonNull Drawable drawable, int width, int height) {
35+
super(drawable);
36+
this.width = width;
37+
this.height = height;
38+
}
39+
40+
@Override
41+
public int getIntrinsicWidth() {
42+
return width;
43+
}
44+
45+
@Override
46+
public int getIntrinsicHeight() {
47+
return height;
48+
}
49+
}

0 commit comments

Comments
 (0)