Skip to content

Instantly share code, notes, and snippets.

@SuperPenguin
Created November 4, 2022 12:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SuperPenguin/5b430ce55ebf66dde7f184db1ebaec15 to your computer and use it in GitHub Desktop.
Save SuperPenguin/5b430ce55ebf66dde7f184db1ebaec15 to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(
MultiBlocProvider(
providers: [
BlocProvider(
create: (context) => ThemeModeCubit(
ThemeMode.light,
),
),
BlocProvider(
create: (context) => AppThemeCubit(
AppTheme(
veryRounded: false,
),
),
),
],
child: const App(),
),
);
}
class ThemeModeCubit extends Cubit<ThemeMode> {
ThemeModeCubit(super.initialState);
void toggle() {
emit(state == ThemeMode.light ? ThemeMode.dark : ThemeMode.light);
}
}
class AppThemeCubit extends Cubit<AppTheme> {
AppThemeCubit(super.initialState);
void toggleVeryRounded() {
emit(
AppTheme(
veryRounded: !state.veryRounded,
),
);
}
}
class AppTheme {
AppTheme({
required this.veryRounded,
});
final bool veryRounded;
ThemeData get lightTheme {
return ThemeData(
brightness: Brightness.light,
extensions: {
MyCardThemeData(
borderRadius: BorderRadius.all(
Radius.circular(
veryRounded ? 16.0 : 2.0,
),
),
backgroundColor: Colors.blue.shade100,
),
},
);
}
ThemeData get darkTheme {
return ThemeData(
brightness: Brightness.dark,
extensions: {
MyCardThemeData(
borderRadius: BorderRadius.all(
Radius.circular(
veryRounded ? 16.0 : 2.0,
),
),
backgroundColor: Colors.red.shade700,
),
},
);
}
}
class App extends StatefulWidget {
const App({super.key});
@override
State<App> createState() => _AppState();
}
class _AppState extends State<App> {
@override
Widget build(BuildContext context) {
final appThemeCubit = context.watch<AppThemeCubit>();
final themeModeCubit = context.watch<ThemeModeCubit>();
return MaterialApp(
themeMode: themeModeCubit.state,
theme: appThemeCubit.state.lightTheme,
darkTheme: appThemeCubit.state.darkTheme,
routes: {
'/': (context) => const HomeScreen(),
},
);
}
}
class MyCard extends StatelessWidget {
const MyCard({
super.key,
required this.child,
});
final Widget child;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final myCardTheme = theme.extension<MyCardThemeData>();
return Card(
shape: RoundedRectangleBorder(
borderRadius: myCardTheme?.borderRadius ?? BorderRadius.zero,
),
color: myCardTheme?.backgroundColor ?? theme.colorScheme.surface,
child: child,
);
}
}
class MyCardThemeData extends ThemeExtension<MyCardThemeData> {
MyCardThemeData({
this.borderRadius,
this.backgroundColor,
});
final BorderRadius? borderRadius;
final Color? backgroundColor;
@override
ThemeExtension<MyCardThemeData> copyWith({
BorderRadius? borderRadius,
Color? backgroundColor,
}) {
return MyCardThemeData(
borderRadius: borderRadius ?? this.borderRadius,
backgroundColor: backgroundColor ?? this.backgroundColor,
);
}
@override
ThemeExtension<MyCardThemeData> lerp(
ThemeExtension<MyCardThemeData>? other,
double t,
) {
if (other is! MyCardThemeData) return this;
return MyCardThemeData(
borderRadius: BorderRadius.lerp(
borderRadius,
other.borderRadius,
t,
),
backgroundColor: Color.lerp(
backgroundColor,
other.backgroundColor,
t,
),
);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is MyCardThemeData &&
borderRadius == other.borderRadius &&
backgroundColor == other.backgroundColor;
}
@override
int get hashCode {
return Object.hashAll([
borderRadius,
backgroundColor,
]);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('App Bar'),
),
body: ListView(
children: [
BlocBuilder<ThemeModeCubit, ThemeMode>(
builder: (context, state) => SwitchListTile.adaptive(
title: const Text('Dark Mode'),
value: state == ThemeMode.dark,
onChanged: (value) => context.read<ThemeModeCubit>().toggle(),
),
),
BlocBuilder<AppThemeCubit, AppTheme>(
builder: (context, state) => SwitchListTile.adaptive(
title: const Text('Very Rounded'),
value: state.veryRounded,
onChanged: (value) =>
context.read<AppThemeCubit>().toggleVeryRounded(),
),
),
const Center(
child: MyCard(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text('My Card Example'),
),
),
),
],
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment