advanced_theme_customizer 0.1.1
advanced_theme_customizer: ^0.1.1 copied to clipboard
Advanced, safe, JSON-driven UI theme customization for Flutter apps.
example/lib/main.dart
import 'package:advanced_theme_customizer/advanced_theme_customizer.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const ExampleHostApp());
}
class ExampleHostApp extends StatefulWidget {
const ExampleHostApp({super.key});
@override
State<ExampleHostApp> createState() => _ExampleHostAppState();
}
class _ExampleHostAppState extends State<ExampleHostApp> {
late final AdvancedCustomizerController _controller;
static const AdvancedComponentRegistry _registry = AdvancedComponentRegistry(
pages: <AdvancedPageDescriptor>[
AdvancedPageDescriptor(pageId: 'home', displayName: 'Home'),
AdvancedPageDescriptor(pageId: 'profile', displayName: 'Profile'),
],
groups: <AdvancedComponentGroupDescriptor>[
AdvancedComponentGroupDescriptor(
groupId: 'home.actions',
pageId: 'home',
displayName: 'Home Actions',
),
AdvancedComponentGroupDescriptor(
groupId: 'profile.actions',
pageId: 'profile',
displayName: 'Profile Actions',
),
],
components: <AdvancedComponentDescriptor>[
AdvancedComponentDescriptor(
componentId: 'home.button.primary',
pageId: 'home',
groupId: 'home.actions',
displayName: 'Home Primary Button',
),
AdvancedComponentDescriptor(
componentId: 'home.button.secondary',
pageId: 'home',
groupId: 'home.actions',
displayName: 'Home Secondary Button',
),
AdvancedComponentDescriptor(
componentId: 'profile.button.primary',
pageId: 'profile',
groupId: 'profile.actions',
displayName: 'Profile Primary Button',
),
],
);
@override
void initState() {
super.initState();
_controller = AdvancedCustomizerController(
config: const AdvancedCustomizerConfig(registry: _registry),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AdvancedCustomizerPreviewBridge(
controller: _controller,
child: MaterialApp(
title: 'Advanced Customizer Example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF1A73E8)),
useMaterial3: true,
),
home: HomePage(controller: _controller),
),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key, required this.controller});
final AdvancedCustomizerController controller;
@override
Widget build(BuildContext context) {
return AdvancedCustomizerInPagePreviewContainer(
controller: controller,
pageId: 'home',
child: Scaffold(
appBar: AppBar(
title: const Text('Home'),
actions: <Widget>[
IconButton(
onPressed: () {
openSettingsModeCustomizer<void>(
context: context,
controller: controller,
);
},
icon: const Icon(Icons.tune),
tooltip: 'Open Global Customizer',
),
],
),
body: ListView(
padding: const EdgeInsets.all(16),
children: <Widget>[
const Text(
'This page demonstrates settings-mode and per-page customization.',
),
const SizedBox(height: 16),
_PreviewButtonCard(
controller: controller,
componentKey: 'home.button.primary',
label: 'Home Primary Action',
),
const SizedBox(height: 12),
_PreviewButtonCard(
controller: controller,
componentKey: 'home.button.secondary',
label: 'Home Secondary Action',
),
const SizedBox(height: 24),
FilledButton(
onPressed: () {
openPageModeCustomizer<void>(
context: context,
controller: controller,
pageId: 'home',
);
},
child: const Text('Customize This Page'),
),
const SizedBox(height: 8),
OutlinedButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (BuildContext context) {
return ProfilePage(controller: controller);
},
),
);
},
child: const Text('Go To Profile Page'),
),
],
),
),
);
}
}
class ProfilePage extends StatelessWidget {
const ProfilePage({super.key, required this.controller});
final AdvancedCustomizerController controller;
@override
Widget build(BuildContext context) {
return AdvancedCustomizerInPagePreviewContainer(
controller: controller,
pageId: 'profile',
child: Scaffold(
appBar: AppBar(title: const Text('Profile')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
_PreviewButtonCard(
controller: controller,
componentKey: 'profile.button.primary',
label: 'Profile Primary Action',
),
const SizedBox(height: 16),
FilledButton(
onPressed: () {
openPageModeCustomizer<void>(
context: context,
controller: controller,
pageId: 'profile',
);
},
child: const Text('Customize Profile Page'),
),
],
),
),
),
);
}
}
class _PreviewButtonCard extends StatelessWidget {
const _PreviewButtonCard({
required this.controller,
required this.componentKey,
required this.label,
});
final AdvancedCustomizerController controller;
final String componentKey;
final String label;
@override
Widget build(BuildContext context) {
return AdvancedCustomizerResolvedColor(
controller: controller,
componentKey: componentKey,
property: AdvancedCustomizerProperty.fill,
fallbackColor: Theme.of(context).colorScheme.primary,
builder: (BuildContext context, Color? fill) {
return AdvancedCustomizerResolvedColor(
controller: controller,
componentKey: componentKey,
property: AdvancedCustomizerProperty.text,
fallbackColor: Theme.of(context).colorScheme.onPrimary,
builder: (BuildContext context, Color? textColor) {
return AdvancedCustomizerResolvedDouble(
controller: controller,
componentKey: componentKey,
property: AdvancedCustomizerProperty.radius,
fallbackValue: 12,
builder: (BuildContext context, double? radius) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: FilledButton(
style: FilledButton.styleFrom(
backgroundColor: fill,
foregroundColor: textColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(radius ?? 12),
),
),
onPressed: () {},
child: Text(label),
),
),
);
},
);
},
);
},
);
}
}