or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

buttons-and-selection.mdfeedback-and-communication.mdindex.mdinput-and-forms.mdlayout-and-containers.mdnavigation-components.mdpickers-and-selection.mdtheming-and-styling.md

theming-and-styling.mddocs/

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

```