cus_theme 1.8.1
cus_theme: ^1.8.1 copied to clipboard
A customizable Flutter theme package with light/dark modes, color presets, typography, spacing, and dynamic theme switching.
Custom Theme Package #
A Flutter package that provides a customizable theme system for your applications.
Easily implement and switch between light and dark themes, customize colors, typography, spacing, and more through a clean, consistent API.
Features #
- Pre-configured light and dark themes
- Custom color schemes and theme presets
- Consistent text styles and typography system
- Spacing, sizing, and animation constants
- Dynamic theme switching (light/dark/custom)
- Theme provider with persistence (using
shared_preferences) - Custom theme extensions for extra properties
- Responsive design utilities
- Type-safe theme access and context extensions
Getting started #
Installation #
Run this command in your project directory:
flutter pub add cus_theme
Or manually add it to your pubspec.yaml:
dependencies:
cus_theme: ^1.8.1
provider: ^6.1.5
shared_preferences: ^2.5.3
Then run:
flutter pub get
Usage #
Basic Usage #
import 'package:flutter/material.dart';
import 'package:cus_theme/cus_theme.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
// Create a theme instance (default is light)
final appTheme = AppTheme();
return MaterialApp(
title: 'Custom Theme Demo',
theme: appTheme.themeData,
home: const MyHomePage(),
);
}
}
// For dark theme
// final darkTheme = AppTheme(isDarkMode: true);
// theme: darkTheme.themeData,
Dynamic Theme with Provider #
For dynamic theme switching and persistence, use the ThemeProvider and the helper:
import 'package:flutter/material.dart';
import 'package:cus_theme/cus_theme.dart';
import 'package:provider/provider.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return wrapWithThemeProvider(
initialDarkMode: false,
child: Consumer<ThemeProvider>(
builder: (context, themeProvider, _) {
return MaterialApp(
title: 'Theme Provider Demo',
theme: themeProvider.themeData,
home: const HomePage(),
);
},
),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Theme Demo')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Current theme: ${context.isDarkMode ? "Dark" : "Light"}',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () => context.toggleTheme(),
child: const Text('Toggle Theme'),
),
],
),
),
);
}
}
Theme Constants #
Use constants for spacing, sizing, and animation:
Container(
margin: EdgeInsets.all(ThemeConstants.spacing16),
padding: ThemeConstants.paddingMedium,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(ThemeConstants.radiusMedium),
color: Colors.blue,
),
child: Text('Hello World'),
);
Theme Colors #
Access color schemes and semantic colors:
Container(
color: ThemeColors.primaryPurple,
child: Text('Primary Purple'),
);
Container(
color: CustomThemeExtension.of(context).success,
child: Text('Success'),
);
Typography #
Use the built-in text styles and helpers:
Text('Headline Large', style: Theme.of(context).textTheme.headlineLarge);
Text('Bold', style: ThemeText.bold(Theme.of(context).textTheme.bodyMedium!));
Text('Colored', style: ThemeText.withColor(Theme.of(context).textTheme.bodyMedium!, Colors.red));
Theme Extensions #
Access extra theme properties and helpers:
final customTheme = CustomThemeExtension.of(context);
Container(
decoration: customTheme.getCardDecoration(elevation: 2.0, isHovered: true),
padding: customTheme.contentPadding,
child: Text('Custom Card'),
);
Row(
children: [
CustomThemeExtension.createTag(context, 'Tag'),
const SizedBox(width: 8),
CustomThemeExtension.createBadge(context, '5'),
const SizedBox(width: 8),
CustomThemeExtension.createRating(context, 4.5),
],
);
Theme Presets #
Switch between built-in color presets:
ElevatedButton(
onPressed: () => context.applyThemePreset('blue'),
child: const Text('Blue Theme'),
);
Customization #
Extending AppTheme #
class MyCustomTheme extends AppTheme {
MyCustomTheme({super.isDarkMode});
@override
ThemeData get _lightTheme {
final baseTheme = super._lightTheme;
return baseTheme.copyWith(
appBarTheme: const AppBarTheme(
centerTitle: true,
elevation: 0,
),
cardTheme: const CardTheme(
clipBehavior: Clip.antiAlias,
margin: EdgeInsets.symmetric(vertical: 8, horizontal: 16),
),
);
}
}
Creating a Custom Theme Extension #
class MyCustomExtension extends ThemeExtension<MyCustomExtension> {
final Color specialColor;
final BorderRadius specialRadius;
MyCustomExtension({
required this.specialColor,
required this.specialRadius,
});
@override
ThemeExtension<MyCustomExtension> copyWith({
Color? specialColor,
BorderRadius? specialRadius,
}) {
return MyCustomExtension(
specialColor: specialColor ?? this.specialColor,
specialRadius: specialRadius ?? this.specialRadius,
);
}
@override
ThemeExtension<MyCustomExtension> lerp(
covariant ThemeExtension<MyCustomExtension>? other,
double t,
) {
if (other is! MyCustomExtension) return this;
return MyCustomExtension(
specialColor: Color.lerp(specialColor, other.specialColor, t)!,
specialRadius: BorderRadius.lerp(specialRadius, other.specialRadius, t)!,
);
}
static MyCustomExtension of(BuildContext context) {
return Theme.of(context).extension<MyCustomExtension>()!;
}
}
API Reference #
Main Classes #
AppTheme– Main theme class, providesThemeDataThemeColors– Color schemes and color utilitiesThemeText– Typography and text style utilitiesThemeConstants– Spacing, sizing, and timing constantsCustomThemeExtension– Additional theme propertiesThemeProvider– State management for dynamic theme changes
Helper Functions #
wrapWithThemeProvider– Wraps your app with ThemeProviderthemeBuilder– Rebuilds when theme changesgetAppTheme– Gets the active AppThemegetCurrentTheme– Gets the current ThemeDatagetCustomTheme– Gets the custom theme extension
Context Extensions #
context.toggleTheme()– Toggle between light and dark modecontext.setDarkMode(bool)– Set dark mode explicitlycontext.setPrimaryColor(Color?)– Set primary colorcontext.setSecondaryColor(Color?)– Set secondary colorcontext.applyThemePreset(String)– Apply a theme presetcontext.themeProvider– Get the theme providercontext.theme– Get current ThemeDatacontext.customTheme– Get custom theme extensioncontext.isDarkMode– Check if theme is dark mode
Additional information #
- For a complete example, see the example directory.
- This package is licensed under the Apache-2.0 License.
- Contributions are welcome! Please submit a Pull Request or open an issue.