Flutter 3 — ThemeData finally Extendeddd…

Lakshay Parnami
3 min readJun 10, 2022

The wait is over, we now have ThemeExtensions in Flutter 3.
I remember we had to create custom workarounds to ‘extend’ ThemeData. all those were not clean, it always felt like the Framework should handle this, and now we’ve ThemeExtension to the rescue.

To begin with, create a custom theme class that extends ThemeExtension<YourClassName>

import 'package:flutter/material.dart';

@immutable
class MyCardTheme extends ThemeExtension<MyCardTheme> {
const MyCardTheme({
this.background = Colors.white,
this.shape = const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(8),
),
),
});

final Color background;
final ShapeBorder shape;

@override
MyCardTheme copyWith({
Color? background,
ShapeBorder? shape,
}) {
return MyCardTheme(
background: background ?? this.background,
shape: shape ?? this.shape,
);
}

@override
MyCardTheme lerp(ThemeExtension<MyCardTheme>? other, double t) {
if (other is! MyCardTheme) {
return this;
}
return MyCardTheme(
background: Color.lerp(background, other.background, t) ?? Colors.white,
shape: ShapeBorder.lerp(shape, other.shape, t) ??
const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(8),
),
),
);
}

@override
String toString() => 'MyCardTheme('
'background: $background, radius: $shape'
')';
}

It is necessary to override the lerp() and copyWith() methods when extending ThemeExtension class.

The lerp() function controls how the properties will change when the theme changes. it will linearly interpolate between two properties for a smoother transition.

Now, create objects for light and dark themes

MyCardTheme lightCardTheme = MyCardTheme(
background: Colors.blueGrey[200]!,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(24),
),
),
);
MyCardTheme darkCardTheme = MyCardTheme(
background: Colors.blueGrey[800]!,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(24),
),
),
);

Add these themes to the extensions array of your ThemeData for both, light and dark themes.

MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.green,
cardTheme: const CardTheme(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(8),
),
),
color: Colors.green,
),
extensions: <ThemeExtension<dynamic>>[
lightCardTheme,
],

),
darkTheme: ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.green,
cardTheme: const CardTheme(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(8),
),
),
color: Colors.green,
),
extensions: <ThemeExtension<dynamic>>[
darkCardTheme,
],

),
home: const MyHomePage(title: 'Themes Extendeddd…'),
);

and you’re good to go!
use these properties by using

MyCardTheme customCardTheme =
Theme.of(context).extension<MyCardTheme>()!;

Sample widget:

class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);

final String title;

@override
Widget build(BuildContext context) {
final MyCardTheme customCardTheme =
Theme.of(context).extension<MyCardTheme>()!;

return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Card(
child: Container(
padding: const EdgeInsets.all(16),
child: const Text('Card styled from default theme')),
),
Card(
shape: customCardTheme.shape,
color: customCardTheme.background,
child: Container(
padding: const EdgeInsets.all(16),
child: const Text('Card styled from custom theme')),
),
Card(
shape: customCardTheme.shape,
child: Container(
padding: const EdgeInsets.all(16),
child: const Text(
'background from default theme, shape from custom theme')),
),
Card(
color: customCardTheme.background,
child: Container(
padding: const EdgeInsets.all(16),
child: const Text(
'background from custom theme, shape from default theme')),
),
],
),
),
);
}
}

Final result:

And in dark mode:

Link to the git repo: https://github.com/lakshparnami/theme_extensions

For more details visit: https://api.flutter.dev/flutter/material/ThemeData/extensions.html

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Lakshay Parnami
Lakshay Parnami

Written by Lakshay Parnami

Hi, I’m Lakshay Parnami. I’m into Mobile Application Development, I work on Android, Flutter & React Native. I’m currently learning iOS development.

No responses yet

Write a response