0
# Theming and Styling
1
2
Material Design theming system including colors, shapes, typography, elevation, and dynamic colors.
3
4
## Core Imports
5
6
```java
7
import com.google.android.material.color.MaterialColors;
8
import com.google.android.material.color.DynamicColors;
9
import com.google.android.material.color.ColorRoles;
10
import com.google.android.material.shape.ShapeAppearanceModel;
11
import com.google.android.material.shape.MaterialShapeDrawable;
12
import com.google.android.material.shape.CornerTreatment;
13
import com.google.android.material.shape.CornerSize;
14
import com.google.android.material.shape.AbsoluteCornerSize;
15
import com.google.android.material.shape.RelativeCornerSize;
16
import com.google.android.material.shape.RoundedCornerTreatment;
17
import com.google.android.material.shape.CutCornerTreatment;
18
import com.google.android.material.elevation.ElevationOverlayProvider;
19
import com.google.android.material.resources.MaterialResources;
20
import com.google.android.material.typography.TypographyUtils;
21
```
22
23
## Material Colors
24
25
Utility class for working with Material Design colors and theme attributes.
26
27
```java { .api }
28
class MaterialColors {
29
// Get color from theme attributes
30
static int getColor(View view, @AttrRes int colorAttributeResId);
31
static int getColor(Context context, @AttrRes int colorAttributeResId, int defaultValue);
32
static int getColor(View view, @AttrRes int colorAttributeResId, int defaultValue);
33
34
// Get ColorStateList from theme attributes
35
static ColorStateList getColorStateList(View view, @AttrRes int colorAttributeResId);
36
static ColorStateList getColorStateList(Context context, @AttrRes int colorAttributeResId, ColorStateList defaultValue);
37
38
// Color layering and blending
39
static int layer(View view, @AttrRes int backgroundColorAttributeResId, @AttrRes int overlayColorAttributeResId);
40
static int layer(View view, @AttrRes int backgroundColorAttributeResId, @AttrRes int overlayColorAttributeResId, float overlayAlpha);
41
static int layer(@ColorInt int backgroundColor, @ColorInt int overlayColor, @FloatRange(from = 0.0, to = 1.0) float overlayAlpha);
42
43
// Alpha composition
44
static int compositeARGBWithAlpha(@ColorInt int originalColor, @IntRange(from = 0, to = 255) int alpha);
45
46
// Color analysis
47
static boolean isColorLight(@ColorInt int color);
48
}
49
```
50
51
### Usage Example
52
53
```java
54
// Get theme colors
55
int primaryColor = MaterialColors.getColor(view, com.google.android.material.R.attr.colorPrimary);
56
int surfaceColor = MaterialColors.getColor(this, com.google.android.material.R.attr.colorSurface, Color.WHITE);
57
58
// Get ColorStateList for different states
59
ColorStateList primaryColorStateList = MaterialColors.getColorStateList(
60
view, com.google.android.material.R.attr.colorPrimary);
61
62
// Layer colors with alpha
63
int layeredColor = MaterialColors.layer(
64
view,
65
com.google.android.material.R.attr.colorSurface,
66
com.google.android.material.R.attr.colorPrimary,
67
0.08f // 8% alpha overlay
68
);
69
70
// Apply elevation overlay
71
int elevatedSurfaceColor = MaterialColors.layer(surfaceColor, primaryColor, 0.05f);
72
73
// Check if color is light for contrast decisions
74
boolean isLight = MaterialColors.isColorLight(backgroundColor);
75
int textColor = isLight ? Color.BLACK : Color.WHITE;
76
77
// Composite color with alpha
78
int transparentColor = MaterialColors.compositeARGBWithAlpha(primaryColor, 128); // 50% alpha
79
```
80
81
## Dynamic Colors
82
83
Support for Android 12+ dynamic color theming (Material You).
84
85
```java { .api }
86
class DynamicColors {
87
// Apply dynamic colors to activities
88
static void applyToActivitiesIfAvailable(Application application);
89
static void applyToActivitiesIfAvailable(Application application, DynamicColorsOptions options);
90
static void applyToActivityIfAvailable(Activity activity);
91
static void applyToActivityIfAvailable(Activity activity, DynamicColorsOptions options);
92
93
// Check dynamic color availability
94
static boolean isDynamicColorAvailable();
95
96
// Context wrapping for dynamic colors
97
static Context wrapContextIfAvailable(Context context);
98
static Context wrapContextIfAvailable(Context context, DynamicColorsOptions options);
99
}
100
101
class DynamicColorsOptions {
102
int getThemeOverlay();
103
OnAppliedCallback getOnAppliedCallback();
104
Precondition getPrecondition();
105
106
interface OnAppliedCallback {
107
void onApplied(DynamicColorsOptions options);
108
}
109
110
interface Precondition {
111
boolean shouldApplyDynamicColors(Activity activity, int theme);
112
}
113
}
114
```
115
116
### Usage Example
117
118
```java
119
// Enable dynamic colors globally in Application class
120
public class MyApplication extends Application {
121
@Override
122
public void onCreate() {
123
super.onCreate();
124
125
// Apply dynamic colors to all activities if available
126
DynamicColors.applyToActivitiesIfAvailable(this);
127
128
// Or with options
129
DynamicColorsOptions options = new DynamicColorsOptions.Builder()
130
.setOnAppliedCallback(appliedOptions -> {
131
Log.d("DynamicColors", "Dynamic colors applied");
132
})
133
.build();
134
DynamicColors.applyToActivitiesIfAvailable(this, options);
135
}
136
}
137
138
// Check if dynamic colors are available
139
if (DynamicColors.isDynamicColorAvailable()) {
140
// Use dynamic colors
141
DynamicColors.applyToActivityIfAvailable(this);
142
} else {
143
// Fallback to static colors
144
setTheme(R.style.AppTheme_StaticColors);
145
}
146
147
// Wrap context for dynamic colors
148
Context dynamicContext = DynamicColors.wrapContextIfAvailable(this);
149
LayoutInflater.from(dynamicContext).inflate(R.layout.dynamic_layout, parent);
150
```
151
152
## Color Roles
153
154
Represents semantic color roles in Material Design color system.
155
156
```java { .api }
157
class ColorRoles {
158
@ColorInt int getAccent();
159
@ColorInt int getOnAccent();
160
@ColorInt int getAccentContainer();
161
@ColorInt int getOnAccentContainer();
162
}
163
```
164
165
## Shape Appearance Model
166
167
Defines the appearance and shape characteristics of Material components.
168
169
```java { .api }
170
class ShapeAppearanceModel {
171
// Factory methods
172
static Builder builder();
173
static Builder builder(Context context, @StyleRes int styleRes, @StyleRes int defaultStyleRes);
174
static Builder builder(Context context, AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes);
175
176
// Corner treatments
177
CornerTreatment getTopLeftCorner();
178
CornerTreatment getTopRightCorner();
179
CornerTreatment getBottomRightCorner();
180
CornerTreatment getBottomLeftCorner();
181
182
// Corner sizes
183
CornerSize getTopLeftCornerSize();
184
CornerSize getTopRightCornerSize();
185
CornerSize getBottomRightCornerSize();
186
CornerSize getBottomLeftCornerSize();
187
188
// Edge treatments
189
EdgeTreatment getTopEdge();
190
EdgeTreatment getRightEdge();
191
EdgeTreatment getBottomEdge();
192
EdgeTreatment getLeftEdge();
193
194
// Builder for modifications
195
Builder toBuilder();
196
197
// Transform corner sizes
198
ShapeAppearanceModel withTransformedCornerSizes(CornerSizeUnaryOperator cornerSizeUnaryOperator);
199
}
200
201
class ShapeAppearanceModel.Builder {
202
// Set all corners
203
Builder setAllCorners(CornerTreatment cornerTreatment);
204
Builder setAllCornerSizes(float cornerSize);
205
Builder setAllCornerSizes(CornerSize cornerSize);
206
207
// Individual corners
208
Builder setTopLeftCorner(CornerTreatment cornerTreatment);
209
Builder setTopLeftCornerSize(float cornerSize);
210
Builder setTopLeftCornerSize(CornerSize cornerSize);
211
Builder setTopRightCorner(CornerTreatment cornerTreatment);
212
Builder setTopRightCornerSize(float cornerSize);
213
Builder setTopRightCornerSize(CornerSize cornerSize);
214
Builder setBottomLeftCorner(CornerTreatment cornerTreatment);
215
Builder setBottomLeftCornerSize(float cornerSize);
216
Builder setBottomLeftCornerSize(CornerSize cornerSize);
217
Builder setBottomRightCorner(CornerTreatment cornerTreatment);
218
Builder setBottomRightCornerSize(float cornerSize);
219
Builder setBottomRightCornerSize(CornerSize cornerSize);
220
221
// Edge treatments
222
Builder setAllEdges(EdgeTreatment edgeTreatment);
223
Builder setTopEdge(EdgeTreatment topEdge);
224
Builder setRightEdge(EdgeTreatment rightEdge);
225
Builder setBottomEdge(EdgeTreatment bottomEdge);
226
Builder setLeftEdge(EdgeTreatment leftEdge);
227
228
// Build
229
ShapeAppearanceModel build();
230
}
231
232
interface ShapeAppearanceModel.CornerSizeUnaryOperator {
233
CornerSize apply(CornerSize cornerSize);
234
}
235
```
236
237
### Usage Example
238
239
```java
240
// Create basic rounded shape
241
ShapeAppearanceModel roundedShape = ShapeAppearanceModel.builder()
242
.setAllCorners(CornerFamily.ROUNDED, 16f)
243
.build();
244
245
// Create cut corner shape
246
ShapeAppearanceModel cutShape = ShapeAppearanceModel.builder()
247
.setAllCorners(CornerFamily.CUT, 8f)
248
.build();
249
250
// Mixed corner styles
251
ShapeAppearanceModel mixedShape = ShapeAppearanceModel.builder()
252
.setTopLeftCorner(CornerFamily.ROUNDED, 16f)
253
.setTopRightCorner(CornerFamily.ROUNDED, 16f)
254
.setBottomLeftCorner(CornerFamily.CUT, 8f)
255
.setBottomRightCorner(CornerFamily.CUT, 8f)
256
.build();
257
258
// Pill shape (fully rounded)
259
ShapeAppearanceModel pillShape = ShapeAppearanceModel.builder()
260
.setAllCorners(CornerFamily.ROUNDED, 50f) // 50% of height
261
.build();
262
263
// Apply to MaterialCardView
264
MaterialCardView cardView = findViewById(R.id.card_view);
265
cardView.setShapeAppearanceModel(roundedShape);
266
267
// Apply to MaterialButton
268
MaterialButton button = findViewById(R.id.button);
269
button.setShapeAppearanceModel(pillShape);
270
271
// Transform existing shape (add 8dp to all corners)
272
ShapeAppearanceModel transformedShape = existingShape.withTransformedCornerSizes(
273
cornerSize -> new AbsoluteCornerSize(cornerSize.getCornerSize(bounds) + 8f)
274
);
275
```
276
277
## Material Shape Drawable
278
279
Drawable that renders Material Design shapes with fill, stroke, and elevation.
280
281
```java { .api }
282
class MaterialShapeDrawable extends Drawable {
283
// Constructors
284
MaterialShapeDrawable();
285
MaterialShapeDrawable(ShapeAppearanceModel shapeAppearanceModel);
286
MaterialShapeDrawable(MaterialShapeDrawableState drawableState);
287
288
// Factory methods with elevation overlay
289
static MaterialShapeDrawable createWithElevationOverlay(Context context);
290
static MaterialShapeDrawable createWithElevationOverlay(Context context, float elevation);
291
292
// Shape appearance
293
void setShapeAppearanceModel(ShapeAppearanceModel shapeAppearanceModel);
294
ShapeAppearanceModel getShapeAppearanceModel();
295
296
// Fill color
297
void setFillColor(ColorStateList fillColor);
298
ColorStateList getFillColor();
299
300
// Stroke
301
void setStroke(float strokeWidth, @ColorInt int strokeColor);
302
void setStroke(float strokeWidth, ColorStateList strokeColor);
303
float getStrokeWidth();
304
ColorStateList getStrokeColor();
305
306
// Elevation and shadow
307
void setElevation(float elevation);
308
float getElevation();
309
void setShadowColor(@ColorInt int shadowColor);
310
int getShadowColor();
311
void setUseTintColorForShadow(boolean useTintColorForShadow);
312
boolean isUseTintColorForShadow();
313
void setShadowCompatibilityMode(int mode);
314
int getShadowCompatibilityMode();
315
316
// Paint style
317
void setPaintStyle(Paint.Style style);
318
Paint.Style getPaintStyle();
319
320
// Interpolation for animations
321
void setInterpolation(float interpolation);
322
float getInterpolation();
323
324
// Parent elevation for relative shadows
325
void setParentAbsoluteElevation(float parentAbsoluteElevation);
326
float getParentAbsoluteElevation();
327
}
328
```
329
330
### Shadow Compatibility Mode Constants
331
332
```java { .api }
333
public static final int SHADOW_COMPAT_MODE_DEFAULT = 0;
334
public static final int SHADOW_COMPAT_MODE_ALWAYS = 1;
335
public static final int SHADOW_COMPAT_MODE_NEVER = 2;
336
```
337
338
### Usage Example
339
340
```java
341
// Create shape drawable with elevation
342
MaterialShapeDrawable shapeDrawable = MaterialShapeDrawable.createWithElevationOverlay(this, 8f);
343
344
// Configure shape
345
ShapeAppearanceModel shape = ShapeAppearanceModel.builder()
346
.setAllCorners(CornerFamily.ROUNDED, 12f)
347
.build();
348
shapeDrawable.setShapeAppearanceModel(shape);
349
350
// Configure colors
351
shapeDrawable.setFillColor(ColorStateList.valueOf(
352
MaterialColors.getColor(this, com.google.android.material.R.attr.colorSurface)));
353
shapeDrawable.setStroke(2f, MaterialColors.getColor(this,
354
com.google.android.material.R.attr.colorOutline));
355
356
// Apply to view background
357
View customView = findViewById(R.id.custom_view);
358
customView.setBackground(shapeDrawable);
359
360
// Animate shape changes
361
ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
362
animator.addUpdateListener(animation -> {
363
float progress = (float) animation.getAnimatedValue();
364
shapeDrawable.setInterpolation(progress);
365
});
366
animator.start();
367
368
// Custom shape for specific use case
369
MaterialShapeDrawable buttonBackground = new MaterialShapeDrawable();
370
buttonBackground.setShapeAppearanceModel(ShapeAppearanceModel.builder()
371
.setAllCorners(CornerFamily.ROUNDED, 20f)
372
.build());
373
buttonBackground.setFillColor(ColorStateList.valueOf(primaryColor));
374
buttonBackground.setElevation(4f);
375
376
MaterialButton customButton = findViewById(R.id.custom_button);
377
customButton.setBackground(buttonBackground);
378
```
379
380
## Corner Treatments and Sizes
381
382
Different corner styles and sizing approaches.
383
384
### Corner Treatments
385
386
```java { .api }
387
class RoundedCornerTreatment extends CornerTreatment {
388
RoundedCornerTreatment();
389
RoundedCornerTreatment(float radius);
390
}
391
392
class CutCornerTreatment extends CornerTreatment {
393
CutCornerTreatment();
394
CutCornerTreatment(float size);
395
}
396
```
397
398
### Corner Sizes
399
400
```java { .api }
401
interface CornerSize {
402
float getCornerSize(RectF bounds);
403
}
404
405
class AbsoluteCornerSize implements CornerSize {
406
AbsoluteCornerSize(float size);
407
float getCornerSize(RectF bounds);
408
}
409
410
class RelativeCornerSize implements CornerSize {
411
RelativeCornerSize(@FloatRange(from = 0.0f, to = 1.0f) float percent);
412
float getCornerSize(RectF bounds);
413
}
414
```
415
416
### Usage Example
417
418
```java
419
// Absolute corner size (fixed pixels/dp)
420
CornerSize absoluteCorner = new AbsoluteCornerSize(16f); // 16dp corners
421
422
// Relative corner size (percentage of view size)
423
CornerSize relativeCorner = new RelativeCornerSize(0.5f); // 50% = circular
424
425
// Custom corner treatments
426
CornerTreatment roundedCorner = new RoundedCornerTreatment(12f);
427
CornerTreatment cutCorner = new CutCornerTreatment(8f);
428
429
// Apply to shape
430
ShapeAppearanceModel customShape = ShapeAppearanceModel.builder()
431
.setTopLeftCorner(roundedCorner)
432
.setTopLeftCornerSize(absoluteCorner)
433
.setBottomRightCorner(cutCorner)
434
.setBottomRightCornerSize(relativeCorner)
435
.build();
436
```
437
438
## Elevation Overlay Provider
439
440
Provides elevation overlay colors for dark themes.
441
442
```java { .api }
443
class ElevationOverlayProvider {
444
ElevationOverlayProvider(Context context);
445
446
// Overlay composition
447
@ColorInt int compositeOverlayWithThemeSurfaceColorIfNeeded(float elevation);
448
@ColorInt int compositeOverlayIfNeeded(@ColorInt int backgroundColor, float elevation);
449
@ColorInt int compositeOverlay(@ColorInt int backgroundColor, float elevation);
450
451
// Overlay alpha calculation
452
int calculateOverlayAlpha(float elevation);
453
454
// Theme colors
455
@ColorInt int getThemeSurfaceColor();
456
@ColorInt int getThemeElevationOverlayColor();
457
boolean isThemeElevationOverlayEnabled();
458
}
459
```
460
461
### Usage Example
462
463
```java
464
ElevationOverlayProvider elevationProvider = new ElevationOverlayProvider(this);
465
466
// Get surface color with elevation overlay
467
int surfaceColor = elevationProvider.getThemeSurfaceColor();
468
int elevatedSurfaceColor = elevationProvider.compositeOverlayWithThemeSurfaceColorIfNeeded(8f);
469
470
// Apply to custom view background
471
View elevatedView = findViewById(R.id.elevated_view);
472
elevatedView.setBackgroundColor(elevatedSurfaceColor);
473
474
// Custom elevation overlay
475
int customColor = Color.parseColor("#121212"); // Dark surface
476
int overlayColor = elevationProvider.compositeOverlay(customColor, 16f);
477
```
478
479
## Material Resources
480
481
Utility methods for accessing Material Design resources and attributes.
482
483
```java { .api }
484
class MaterialResources {
485
// ColorStateList from attributes
486
static ColorStateList getColorStateList(Context context, TypedArray attributes, @StyleableRes int index);
487
static ColorStateList getColorStateList(Context context, @ColorRes int colorRes);
488
489
// Drawable from attributes
490
static Drawable getDrawable(Context context, TypedArray attributes, @StyleableRes int index);
491
492
// Text appearance from attributes
493
static TextAppearance getTextAppearance(Context context, TypedArray attributes, @StyleableRes int index);
494
495
// Dimension from attributes
496
static int getDimensionPixelSize(Context context, TypedArray attributes, @StyleableRes int index, int defaultValue);
497
498
// Boolean and integer resources
499
static boolean getBoolean(Context context, @BoolRes int boolRes, boolean defaultValue);
500
static int getInteger(Context context, @IntegerRes int integerRes, int defaultValue);
501
}
502
```
503
504
## Typography Utils
505
506
Utilities for applying Material Design typography.
507
508
```java { .api }
509
class TypographyUtils {
510
// Apply text appearance to TextView
511
static void applyTypography(TextView textView, TextAppearance textAppearance);
512
513
// Resolve text appearance from style resource
514
static TextAppearance resolveTextAppearance(Context context, @StyleRes int textAppearanceStyleRes);
515
}
516
```
517
518
## Complete Theming Example
519
520
Example showing comprehensive Material theming implementation:
521
522
```java
523
public class ThemingExampleActivity extends AppCompatActivity {
524
525
@Override
526
protected void onCreate(Bundle savedInstanceState) {
527
super.onCreate(savedInstanceState);
528
529
// Apply dynamic colors if available
530
if (DynamicColors.isDynamicColorAvailable()) {
531
DynamicColors.applyToActivityIfAvailable(this);
532
}
533
534
setContentView(R.layout.activity_theming_example);
535
536
setupCustomTheming();
537
setupShapeTheming();
538
setupElevationTheming();
539
}
540
541
private void setupCustomTheming() {
542
// Get theme colors
543
int primaryColor = MaterialColors.getColor(this, com.google.android.material.R.attr.colorPrimary);
544
int surfaceColor = MaterialColors.getColor(this, com.google.android.material.R.attr.colorSurface);
545
int onSurfaceColor = MaterialColors.getColor(this, com.google.android.material.R.attr.colorOnSurface);
546
547
// Apply colors to custom views
548
View headerView = findViewById(R.id.header_view);
549
headerView.setBackgroundColor(primaryColor);
550
551
TextView titleText = findViewById(R.id.title_text);
552
titleText.setTextColor(MaterialColors.getColor(this, com.google.android.material.R.attr.colorOnPrimary));
553
554
// Create layered color for subtle accent
555
int accentColor = MaterialColors.layer(surfaceColor, primaryColor, 0.12f);
556
View accentView = findViewById(R.id.accent_view);
557
accentView.setBackgroundColor(accentColor);
558
559
// Dynamic text color based on background
560
boolean isLightBackground = MaterialColors.isColorLight(surfaceColor);
561
int adaptiveTextColor = isLightBackground ?
562
MaterialColors.getColor(this, com.google.android.material.R.attr.colorOnSurface) :
563
MaterialColors.getColor(this, com.google.android.material.R.attr.colorOnSurface);
564
565
TextView bodyText = findViewById(R.id.body_text);
566
bodyText.setTextColor(adaptiveTextColor);
567
}
568
569
private void setupShapeTheming() {
570
// Card with custom shape
571
MaterialCardView cardView = findViewById(R.id.themed_card);
572
ShapeAppearanceModel cardShape = ShapeAppearanceModel.builder()
573
.setTopLeftCorner(CornerFamily.ROUNDED, 16f)
574
.setTopRightCorner(CornerFamily.ROUNDED, 16f)
575
.setBottomLeftCorner(CornerFamily.CUT, 8f)
576
.setBottomRightCorner(CornerFamily.CUT, 8f)
577
.build();
578
cardView.setShapeAppearanceModel(cardShape);
579
580
// Button with pill shape
581
MaterialButton pillButton = findViewById(R.id.pill_button);
582
ShapeAppearanceModel pillShape = ShapeAppearanceModel.builder()
583
.setAllCorners(CornerFamily.ROUNDED, 50f)
584
.build();
585
pillButton.setShapeAppearanceModel(pillShape);
586
587
// Image with custom shape
588
ShapeableImageView imageView = findViewById(R.id.shaped_image);
589
ShapeAppearanceModel imageShape = ShapeAppearanceModel.builder()
590
.setAllCorners(CornerFamily.ROUNDED, 12f)
591
.build();
592
imageView.setShapeAppearanceModel(imageShape);
593
imageView.setStrokeWidth(2f);
594
imageView.setStrokeColor(ColorStateList.valueOf(
595
MaterialColors.getColor(this, com.google.android.material.R.attr.colorOutline)));
596
597
// Custom drawable with shape
598
MaterialShapeDrawable customDrawable = new MaterialShapeDrawable();
599
customDrawable.setShapeAppearanceModel(ShapeAppearanceModel.builder()
600
.setAllCorners(CornerFamily.ROUNDED, 8f)
601
.build());
602
customDrawable.setFillColor(ColorStateList.valueOf(
603
MaterialColors.getColor(this, com.google.android.material.R.attr.colorSurfaceVariant)));
604
customDrawable.setStroke(1f, MaterialColors.getColor(this,
605
com.google.android.material.R.attr.colorOutline));
606
607
View customView = findViewById(R.id.custom_shaped_view);
608
customView.setBackground(customDrawable);
609
}
610
611
private void setupElevationTheming() {
612
ElevationOverlayProvider elevationProvider = new ElevationOverlayProvider(this);
613
614
// Apply elevation overlays to views
615
View[] elevatedViews = {
616
findViewById(R.id.elevation_2dp),
617
findViewById(R.id.elevation_4dp),
618
findViewById(R.id.elevation_8dp),
619
findViewById(R.id.elevation_16dp)
620
};
621
622
float[] elevations = {2f, 4f, 8f, 16f};
623
624
for (int i = 0; i < elevatedViews.length; i++) {
625
View view = elevatedViews[i];
626
float elevation = elevations[i];
627
628
// Create elevated background
629
MaterialShapeDrawable background = MaterialShapeDrawable.createWithElevationOverlay(this, elevation);
630
background.setShapeAppearanceModel(ShapeAppearanceModel.builder()
631
.setAllCorners(CornerFamily.ROUNDED, 8f)
632
.build());
633
634
view.setBackground(background);
635
view.setElevation(elevation);
636
637
// Add elevation text
638
TextView elevationText = view.findViewById(R.id.elevation_text);
639
if (elevationText != null) {
640
elevationText.setText(String.format("%.0fdp", elevation));
641
}
642
}
643
644
// Animated elevation change
645
MaterialButton elevationButton = findViewById(R.id.elevation_button);
646
elevationButton.setOnClickListener(v -> animateElevation(v));
647
}
648
649
private void animateElevation(View view) {
650
float startElevation = view.getElevation();
651
float endElevation = startElevation == 2f ? 16f : 2f;
652
653
ValueAnimator elevationAnimator = ValueAnimator.ofFloat(startElevation, endElevation);
654
elevationAnimator.setDuration(300);
655
elevationAnimator.addUpdateListener(animation -> {
656
float elevation = (float) animation.getAnimatedValue();
657
view.setElevation(elevation);
658
659
// Update background overlay
660
ElevationOverlayProvider provider = new ElevationOverlayProvider(this);
661
int overlayColor = provider.compositeOverlayWithThemeSurfaceColorIfNeeded(elevation);
662
view.setBackgroundColor(overlayColor);
663
});
664
elevationAnimator.start();
665
}
666
667
// Theme switching example
668
private void switchToCustomTheme() {
669
// Save current theme preference
670
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
671
prefs.edit().putString("theme", "custom").apply();
672
673
// Recreate activity to apply new theme
674
recreate();
675
}
676
}
677
678
// Application class for global theming setup
679
public class MyApplication extends Application {
680
@Override
681
public void onCreate() {
682
super.onCreate();
683
684
// Enable dynamic colors globally
685
DynamicColors.applyToActivitiesIfAvailable(this, new DynamicColorsOptions.Builder()
686
.setOnAppliedCallback(options -> {
687
Log.d("DynamicColors", "Dynamic colors applied successfully");
688
})
689
.setPrecondition((activity, theme) -> {
690
// Only apply to certain activities or themes
691
return !activity.getClass().getSimpleName().equals("SplashActivity");
692
})
693
.build());
694
}
695
}
696
```