Skip to content

Commit 115313c

Browse files
ymariandsn5ft
authored andcommitted
Expose a class for themeoverlay in style
This moves functionality from ThemeEnforcement into a stand alone class. Resolves #665 PiperOrigin-RevId: 275481343
1 parent 213d9cd commit 115313c

File tree

23 files changed

+300
-104
lines changed

23 files changed

+300
-104
lines changed

lib/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ def srcDirs = [
6767
'com/google/android/material/textfield',
6868
'com/google/android/material/textview',
6969
'com/google/android/material/theme',
70+
'com/google/android/material/theme/overlay',
7071
'com/google/android/material/transformation',
7172
'com/google/android/material/typography',
7273
]

lib/java/com/google/android/material/appbar/MaterialToolbar.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import com.google.android.material.R;
2020

21-
import static com.google.android.material.internal.ThemeEnforcement.createThemedContext;
21+
import static com.google.android.material.theme.overlay.MaterialThemeOverlay.wrap;
2222

2323
import android.content.Context;
2424
import android.content.res.ColorStateList;
@@ -69,7 +69,7 @@ public MaterialToolbar(@NonNull Context context, @Nullable AttributeSet attrs) {
6969
}
7070

7171
public MaterialToolbar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
72-
super(createThemedContext(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
72+
super(wrap(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
7373
// Ensure we are using the correctly themed context rather than the context that was passed in.
7474
context = getContext();
7575

lib/java/com/google/android/material/bottomappbar/BottomAppBar.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818

1919
import com.google.android.material.R;
2020

21-
import static com.google.android.material.internal.ThemeEnforcement.createThemedContext;
2221
import static com.google.android.material.shape.MaterialShapeDrawable.SHADOW_COMPAT_MODE_ALWAYS;
22+
import static com.google.android.material.theme.overlay.MaterialThemeOverlay.wrap;
2323

2424
import android.animation.Animator;
2525
import android.animation.AnimatorListenerAdapter;
@@ -216,7 +216,7 @@ public BottomAppBar(@NonNull Context context, @Nullable AttributeSet attrs) {
216216
}
217217

218218
public BottomAppBar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
219-
super(createThemedContext(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
219+
super(wrap(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
220220
// Ensure we are using the correctly themed context rather than the context that was passed in.
221221
context = getContext();
222222

lib/java/com/google/android/material/bottomnavigation/BottomNavigationView.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import com.google.android.material.R;
2020

21-
import static com.google.android.material.internal.ThemeEnforcement.createThemedContext;
21+
import static com.google.android.material.theme.overlay.MaterialThemeOverlay.wrap;
2222

2323
import android.content.Context;
2424
import android.content.res.ColorStateList;
@@ -134,7 +134,7 @@ public BottomNavigationView(@NonNull Context context, @Nullable AttributeSet att
134134

135135
public BottomNavigationView(
136136
@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
137-
super(createThemedContext(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
137+
super(wrap(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
138138
// Ensure we are using the correctly themed context rather than the context that was passed in.
139139
context = getContext();
140140

lib/java/com/google/android/material/button/MaterialButton.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import com.google.android.material.R;
2020

2121
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
22-
import static com.google.android.material.internal.ThemeEnforcement.createThemedContext;
22+
import static com.google.android.material.theme.overlay.MaterialThemeOverlay.wrap;
2323

2424
import android.content.Context;
2525
import android.content.res.ColorStateList;
@@ -192,7 +192,7 @@ public MaterialButton(@NonNull Context context, @Nullable AttributeSet attrs) {
192192
}
193193

194194
public MaterialButton(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
195-
super(createThemedContext(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
195+
super(wrap(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
196196
// Ensure we are using the correctly themed context rather than the context that was passed in.
197197
context = getContext();
198198

lib/java/com/google/android/material/card/MaterialCardView.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import com.google.android.material.R;
2020

21-
import static com.google.android.material.internal.ThemeEnforcement.createThemedContext;
21+
import static com.google.android.material.theme.overlay.MaterialThemeOverlay.wrap;
2222

2323
import android.content.Context;
2424
import android.content.res.ColorStateList;
@@ -115,7 +115,7 @@ public MaterialCardView(Context context, AttributeSet attrs) {
115115
}
116116

117117
public MaterialCardView(Context context, AttributeSet attrs, int defStyleAttr) {
118-
super(createThemedContext(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
118+
super(wrap(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
119119
isParentCardViewDoneInitializing = true;
120120
// Ensure we are using the correctly themed context rather than the context that was passed in.
121121
context = getContext();

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import com.google.android.material.R;
2020

21-
import static com.google.android.material.internal.ThemeEnforcement.createThemedContext;
21+
import static com.google.android.material.theme.overlay.MaterialThemeOverlay.wrap;
2222

2323
import android.content.Context;
2424
import android.content.res.ColorStateList;
@@ -62,7 +62,7 @@ public MaterialCheckBox(Context context, @Nullable AttributeSet attrs) {
6262
}
6363

6464
public MaterialCheckBox(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
65-
super(createThemedContext(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
65+
super(wrap(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
6666
// Ensure we are using the correctly themed context rather than the context that was passed in.
6767
context = getContext();
6868

lib/java/com/google/android/material/dialog/MaterialAlertDialogBuilder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
import com.google.android.material.R;
2020

21-
import static com.google.android.material.internal.ThemeEnforcement.createThemedContext;
21+
import static com.google.android.material.theme.overlay.MaterialThemeOverlay.wrap;
2222

2323
import android.content.Context;
2424
import android.content.DialogInterface.OnCancelListener;
@@ -86,7 +86,7 @@ private static int getMaterialAlertDialogThemeOverlay(@NonNull Context context)
8686

8787
private static Context createMaterialAlertDialogThemedContext(@NonNull Context context) {
8888
int themeOverlayId = getMaterialAlertDialogThemeOverlay(context);
89-
Context themedContext = createThemedContext(context, null, DEF_STYLE_ATTR, DEF_STYLE_RES);
89+
Context themedContext = wrap(context, null, DEF_STYLE_ATTR, DEF_STYLE_RES);
9090
if (themeOverlayId == 0) {
9191
return themedContext;
9292
}

lib/java/com/google/android/material/floatingactionbutton/FloatingActionButton.java

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

2121
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
2222
import static androidx.core.util.Preconditions.checkNotNull;
23-
import static com.google.android.material.internal.ThemeEnforcement.createThemedContext;
23+
import static com.google.android.material.theme.overlay.MaterialThemeOverlay.wrap;
2424

2525
import android.animation.Animator.AnimatorListener;
2626
import android.content.Context;
@@ -203,7 +203,7 @@ public FloatingActionButton(@NonNull Context context, @Nullable AttributeSet att
203203
@SuppressWarnings("initialization")
204204
public FloatingActionButton(
205205
@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
206-
super(createThemedContext(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
206+
super(wrap(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr);
207207
// Ensure we are using the correctly themed context rather than the context that was passed in.
208208
context = getContext();
209209

lib/java/com/google/android/material/internal/ThemeEnforcement.java

Lines changed: 0 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import androidx.annotation.RestrictTo;
2929
import androidx.annotation.StyleRes;
3030
import androidx.annotation.StyleableRes;
31-
import androidx.appcompat.view.ContextThemeWrapper;
3231
import androidx.appcompat.widget.TintTypedArray;
3332
import android.util.AttributeSet;
3433
import android.util.TypedValue;
@@ -47,10 +46,6 @@ public final class ThemeEnforcement {
4746
private static final int[] MATERIAL_CHECK_ATTRS = {R.attr.colorPrimaryVariant};
4847
private static final String MATERIAL_THEME_NAME = "Theme.MaterialComponents";
4948

50-
private static final int[] ANDROID_THEME_OVERLAY_ATTRS =
51-
new int[] {android.R.attr.theme, R.attr.theme};
52-
private static final int[] MATERIAL_THEME_OVERLAY_ATTR = new int[] {R.attr.materialThemeOverlay};
53-
5449
private ThemeEnforcement() {}
5550

5651
/**
@@ -251,72 +246,4 @@ private static void checkTheme(
251246
+ " (or a descendant).");
252247
}
253248
}
254-
255-
/**
256-
* Uses the materialThemeOverlay attribute to create a themed context. This allows us to use
257-
* ThemeOverlays with a default style, and gives us some protection against losing our
258-
* ThemeOverlay by clients who set android:theme or app:theme. If android:theme or app:theme is
259-
* specified by the client, any attributes defined there will take precedence over attributes
260-
* defined in materialThemeOverlay.
261-
*/
262-
@NonNull
263-
public static Context createThemedContext(
264-
@NonNull Context context,
265-
@Nullable AttributeSet attrs,
266-
@AttrRes int defStyleAttr,
267-
@StyleRes int defStyleRes) {
268-
int materialThemeOverlayId =
269-
obtainMaterialThemeOverlayId(context, attrs, defStyleAttr, defStyleRes);
270-
if (materialThemeOverlayId != 0
271-
&& (!(context instanceof ContextThemeWrapper)
272-
|| ((ContextThemeWrapper) context).getThemeResId() != materialThemeOverlayId)) {
273-
// If the context isn't a ContextThemeWrapper, or it is but does not have the same theme as we
274-
// need, wrap it in a new wrapper.
275-
context = new ContextThemeWrapper(context, materialThemeOverlayId);
276-
277-
// We want values set in android:theme or app:theme to always override values supplied by
278-
// materialThemeOverlay, so we'll wrap the context again if either of those are set.
279-
int androidThemeOverlayId = obtainAndroidThemeOverlayId(context, attrs);
280-
if (androidThemeOverlayId != 0) {
281-
context = new ContextThemeWrapper(context, androidThemeOverlayId);
282-
}
283-
}
284-
return context;
285-
}
286-
287-
/**
288-
* Retrieves the value of {@code android:theme} or {@code app:theme}, not taking into account
289-
* {@code defStyleAttr} and {@code defStyleRes} because the Android theme overlays shouldn't work
290-
* from default styles.
291-
*/
292-
@StyleRes
293-
private static int obtainAndroidThemeOverlayId(@NonNull Context context, AttributeSet attrs) {
294-
TypedArray a = context.obtainStyledAttributes(attrs, ANDROID_THEME_OVERLAY_ATTRS);
295-
int androidThemeId = a.getResourceId(0 /* index */, 0 /* defaultVal */);
296-
int appThemeId = a.getResourceId(1 /* index */, 0 /* defaultVal */);
297-
a.recycle();
298-
if (androidThemeId != 0) {
299-
return androidThemeId;
300-
} else {
301-
return appThemeId;
302-
}
303-
}
304-
305-
/**
306-
* Retrieves the value of {@code materialThemeOverlay}, taking into account {@code defStyleAttr}
307-
* and {@code defStyleRes} because the Material theme overlay should work from default styles.
308-
*/
309-
@StyleRes
310-
private static int obtainMaterialThemeOverlayId(
311-
@NonNull Context context,
312-
@Nullable AttributeSet attrs,
313-
@AttrRes int defStyleAttr,
314-
@StyleRes int defStyleRes) {
315-
TypedArray a =
316-
context.obtainStyledAttributes(
317-
attrs, MATERIAL_THEME_OVERLAY_ATTR, defStyleAttr, defStyleRes);
318-
int materialThemeOverlayId = a.getResourceId(0 /* index */, 0 /* defaultVal */);
319-
a.recycle();
320-
return materialThemeOverlayId;
321-
}
322249
}

0 commit comments

Comments
 (0)