empty_view 2.1.1
empty_view: ^2.1.1 copied to clipboard
A powerful Flutter package for displaying beautiful empty state views with animations, Lottie support, presets, shimmer loading, dark mode, and accessibility features.
import 'package:flutter/material.dart';
import 'package:empty_view/empty_view.dart';
import 'package:google_fonts/google_fonts.dart';
void main() {
// Disable Google Fonts file caching to avoid path_provider issues
GoogleFonts.config.allowRuntimeFetching = true;
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
// Create base text theme with Google Fonts
final textTheme = GoogleFonts.poppinsTextTheme();
return MaterialApp(
title: 'Empty View Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF6366F1),
brightness: Brightness.light,
),
useMaterial3: true,
textTheme: textTheme.copyWith(
headlineLarge: GoogleFonts.plusJakartaSans(
fontSize: 32,
fontWeight: FontWeight.w800,
letterSpacing: -0.5,
),
headlineMedium: GoogleFonts.plusJakartaSans(
fontSize: 28,
fontWeight: FontWeight.w700,
letterSpacing: -0.3,
),
titleLarge: GoogleFonts.plusJakartaSans(
fontSize: 22,
fontWeight: FontWeight.w600,
),
titleMedium: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w600,
),
bodyLarge: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w400,
),
bodyMedium: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w400,
),
labelLarge: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
appBarTheme: AppBarTheme(
centerTitle: true,
elevation: 0,
titleTextStyle: GoogleFonts.plusJakartaSans(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Colors.black87,
),
),
),
darkTheme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF6366F1),
brightness: Brightness.dark,
),
useMaterial3: true,
textTheme: textTheme.copyWith(
headlineLarge: GoogleFonts.plusJakartaSans(
fontSize: 32,
fontWeight: FontWeight.w800,
letterSpacing: -0.5,
color: Colors.white,
),
headlineMedium: GoogleFonts.plusJakartaSans(
fontSize: 28,
fontWeight: FontWeight.w700,
letterSpacing: -0.3,
color: Colors.white,
),
titleLarge: GoogleFonts.plusJakartaSans(
fontSize: 22,
fontWeight: FontWeight.w600,
color: Colors.white,
),
titleMedium: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.white,
),
bodyLarge: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w400,
color: Colors.white70,
),
bodyMedium: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w400,
color: Colors.white70,
),
labelLarge: GoogleFonts.poppins(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
appBarTheme: AppBarTheme(
centerTitle: true,
elevation: 0,
titleTextStyle: GoogleFonts.plusJakartaSans(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
),
themeMode: ThemeMode.system,
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Scaffold(
body: SafeArea(
child: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.fromLTRB(24, 40, 24, 32),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 6,
),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
theme.colorScheme.primary,
theme.colorScheme.secondary,
],
),
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: theme.colorScheme.primary.withValues(alpha: 0.3),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: Text(
'v2.1.0',
style: GoogleFonts.spaceMono(
fontSize: 12,
fontWeight: FontWeight.w700,
color: Colors.white,
letterSpacing: 1,
),
),
),
const SizedBox(height: 20),
ShaderMask(
shaderCallback: (bounds) => LinearGradient(
colors: [
theme.colorScheme.primary,
theme.colorScheme.tertiary,
],
).createShader(bounds),
child: Text(
'Empty View',
style: GoogleFonts.plusJakartaSans(
fontSize: 36,
fontWeight: FontWeight.w800,
letterSpacing: -1,
color: Colors.white,
),
),
),
const SizedBox(height: 8),
Text(
'Beautiful empty states for Flutter apps',
style: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w400,
color: theme.colorScheme.onSurfaceVariant,
height: 1.5,
),
),
const SizedBox(height: 24),
// Demo GIF showcase
ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: theme.colorScheme.primary.withValues(alpha: 0.2),
blurRadius: 20,
offset: const Offset(0, 10),
),
],
),
child: Image.asset(
'assets/demo.gif',
width: double.infinity,
fit: BoxFit.cover,
),
),
),
],
),
),
),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 16),
sliver: SliverGrid(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 12,
crossAxisSpacing: 12,
childAspectRatio: 1.1,
),
delegate: SliverChildListDelegate([
_FeatureCard(
icon: Icons.auto_awesome,
title: 'Presets',
subtitle: '16 ready-to-use',
color: Colors.purple,
onTap: () => _navigate(context, const PresetsDemo()),
),
_FeatureCard(
icon: Icons.animation,
title: 'Animations',
subtitle: '5 entrance effects',
color: Colors.blue,
onTap: () => _navigate(context, const AnimationsDemo()),
),
_FeatureCard(
icon: Icons.gradient,
title: 'Gradients',
subtitle: 'NEW in v2.1',
color: Colors.deepPurple,
onTap: () => _navigate(context, const GradientDemo()),
),
_FeatureCard(
icon: Icons.build_circle,
title: 'Builder',
subtitle: 'NEW in v2.1',
color: Colors.cyan,
onTap: () => _navigate(context, const BuilderDemo()),
),
_FeatureCard(
icon: Icons.play_circle_outline,
title: 'Lottie',
subtitle: 'Animated graphics',
color: Colors.orange,
onTap: () => _navigate(context, const LottieDemo()),
),
_FeatureCard(
icon: Icons.blur_on,
title: 'Shimmer',
subtitle: 'Skeleton loading',
color: Colors.teal,
onTap: () => _navigate(context, const ShimmerDemo()),
),
_FeatureCard(
icon: Icons.category,
title: 'Icons',
subtitle: 'Material icons',
color: Colors.pink,
onTap: () => _navigate(context, const IconsDemo()),
),
_FeatureCard(
icon: Icons.palette,
title: 'Styling',
subtitle: 'Custom themes',
color: Colors.indigo,
onTap: () => _navigate(context, const StylingDemo()),
),
_FeatureCard(
icon: Icons.cases_rounded,
title: 'Real World',
subtitle: 'Live examples',
color: Colors.green,
onTap: () => _navigate(context, const RealWorldDemo()),
),
]),
),
),
const SliverToBoxAdapter(child: SizedBox(height: 32)),
],
),
),
);
}
void _navigate(BuildContext context, Widget page) {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => page),
);
}
}
class _FeatureCard extends StatelessWidget {
final IconData icon;
final String title;
final String subtitle;
final Color color;
final VoidCallback onTap;
const _FeatureCard({
required this.icon,
required this.title,
required this.subtitle,
required this.color,
required this.onTap,
});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
return Material(
color: isDark ? theme.colorScheme.surfaceContainerHighest : Colors.white,
borderRadius: BorderRadius.circular(16),
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(16),
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: theme.colorScheme.outlineVariant.withValues(alpha: 0.5),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: color.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(12),
),
child: Icon(icon, color: color, size: 24),
),
const Spacer(),
Text(
title,
style: GoogleFonts.plusJakartaSans(
fontSize: 15,
fontWeight: FontWeight.w700,
letterSpacing: -0.2,
),
),
const SizedBox(height: 4),
Text(
subtitle,
style: GoogleFonts.poppins(
fontSize: 12,
fontWeight: FontWeight.w400,
color: theme.colorScheme.onSurfaceVariant,
),
),
],
),
),
),
);
}
}
// ============ PRESETS DEMO ============
class PresetsDemo extends StatefulWidget {
const PresetsDemo({super.key});
@override
State<PresetsDemo> createState() => _PresetsDemoState();
}
class _PresetsDemoState extends State<PresetsDemo> {
final PageController _controller = PageController();
int _currentPage = 0;
final List<_PresetItem> _presets = [
_PresetItem('No Internet', Icons.wifi_off, Colors.grey),
_PresetItem('Empty Cart', Icons.shopping_cart, Colors.orange),
_PresetItem('No Results', Icons.search_off, Colors.blue),
_PresetItem('Error', Icons.error_outline, Colors.red),
_PresetItem('No Messages', Icons.message, Colors.green),
_PresetItem('No Favorites', Icons.favorite, Colors.pink),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Presets')),
body: Column(
children: [
Expanded(
child: PageView(
controller: _controller,
onPageChanged: (i) => setState(() => _currentPage = i),
children: [
EmptyViewPresets.noInternet(onRetry: () {}),
EmptyViewPresets.emptyCart(onShopNow: () {}),
EmptyViewPresets.noSearchResults(searchTerm: 'flutter'),
EmptyViewPresets.error(message: 'Failed to load data'),
EmptyViewPresets.noMessages(onNewMessage: () {}),
EmptyViewPresets.noFavorites(onBrowse: () {}),
],
),
),
SafeArea(
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
_presets.length,
(i) => Container(
width: 8,
height: 8,
margin: const EdgeInsets.symmetric(horizontal: 4),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _currentPage == i
? Theme.of(context).colorScheme.primary
: Theme.of(context).colorScheme.outlineVariant,
),
),
),
),
const SizedBox(height: 16),
Text(
_presets[_currentPage].name,
style: GoogleFonts.plusJakartaSans(
fontSize: 18,
fontWeight: FontWeight.w700,
letterSpacing: -0.3,
),
),
],
),
),
),
],
),
);
}
}
class _PresetItem {
final String name;
final IconData icon;
final Color color;
_PresetItem(this.name, this.icon, this.color);
}
// ============ ANIMATIONS DEMO ============
class AnimationsDemo extends StatefulWidget {
const AnimationsDemo({super.key});
@override
State<AnimationsDemo> createState() => _AnimationsDemoState();
}
class _AnimationsDemoState extends State<AnimationsDemo> {
EmptyViewAnimation _selectedAnimation = EmptyViewAnimation.fadeIn;
int _key = 0;
final List<_AnimationOption> _animations = [
_AnimationOption('Fade In', EmptyViewAnimation.fadeIn),
_AnimationOption('Slide Up', EmptyViewAnimation.slideUp),
_AnimationOption('Scale', EmptyViewAnimation.scale),
_AnimationOption('Bounce', EmptyViewAnimation.bounce),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Animations')),
body: Column(
children: [
Expanded(
child: EmptyView(
key: ValueKey(_key),
icon: Icons.animation,
iconColor: Colors.purple,
iconSize: 80,
showIconBackground: true,
iconBackgroundColor: Colors.purple.withValues(alpha: 0.1),
title: 'Smooth Animations',
description: 'Beautiful entrance animations for your empty states',
animationType: _selectedAnimation,
animationDuration: const Duration(milliseconds: 800),
),
),
SafeArea(
child: Container(
padding: const EdgeInsets.all(20),
child: Wrap(
spacing: 8,
runSpacing: 8,
alignment: WrapAlignment.center,
children: _animations.map((anim) {
final isSelected = _selectedAnimation == anim.type;
return ChoiceChip(
label: Text(anim.name),
selected: isSelected,
onSelected: (_) {
setState(() {
_selectedAnimation = anim.type;
_key++;
});
},
);
}).toList(),
),
),
),
],
),
);
}
}
class _AnimationOption {
final String name;
final EmptyViewAnimation type;
_AnimationOption(this.name, this.type);
}
// ============ LOTTIE DEMO ============
class LottieDemo extends StatelessWidget {
const LottieDemo({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Lottie Animation')),
body: EmptyView(
lottiePath: 'https://assets10.lottiefiles.com/packages/lf20_ysrn2iwp.json',
lottieRepeat: true,
title: 'Lottie Support',
description: 'Display beautiful animated graphics from Lottie files or network URLs',
buttonText: 'Learn More',
onButtonTap: () {},
animationType: EmptyViewAnimation.fadeIn,
style: const EmptyViewStyle(
imageWidthFactor: 0.6,
imageHeightFactor: 0.3,
),
),
);
}
}
// ============ SHIMMER DEMO ============
class ShimmerDemo extends StatefulWidget {
const ShimmerDemo({super.key});
@override
State<ShimmerDemo> createState() => _ShimmerDemoState();
}
class _ShimmerDemoState extends State<ShimmerDemo> {
bool _isLoading = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Shimmer Loading')),
body: Column(
children: [
Expanded(
child: _isLoading
? EmptyView.skeleton()
: EmptyView(
icon: Icons.check_circle,
iconColor: Colors.green,
iconSize: 80,
showIconBackground: true,
iconBackgroundColor: Colors.green.withValues(alpha: 0.1),
title: 'Content Loaded',
description: 'The shimmer skeleton is replaced with actual content',
animationType: EmptyViewAnimation.fadeIn,
),
),
SafeArea(
child: Padding(
padding: const EdgeInsets.all(24),
child: SizedBox(
width: double.infinity,
child: FilledButton.icon(
onPressed: () => setState(() => _isLoading = !_isLoading),
icon: Icon(_isLoading ? Icons.visibility : Icons.refresh),
label: Text(_isLoading ? 'Show Content' : 'Show Shimmer'),
),
),
),
),
],
),
);
}
}
// ============ ICONS DEMO ============
class IconsDemo extends StatelessWidget {
const IconsDemo({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Icon Support')),
body: PageView(
children: [
EmptyView(
icon: Icons.cloud_off_rounded,
iconColor: Colors.blue,
iconSize: 80,
showIconBackground: true,
iconBackgroundColor: Colors.blue.withValues(alpha: 0.1),
title: 'Icon with Background',
description: 'Icons can be displayed with a circular background container',
animationType: EmptyViewAnimation.scale,
),
EmptyView(
icon: Icons.inbox_rounded,
iconColor: Colors.grey,
iconSize: 80,
title: 'Simple Icon',
description: 'Or display icons without any background',
animationType: EmptyViewAnimation.fadeIn,
),
],
),
);
}
}
// ============ STYLING DEMO ============
class StylingDemo extends StatelessWidget {
const StylingDemo({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Custom Styling')),
body: EmptyView(
icon: Icons.palette_rounded,
iconColor: Colors.indigo,
iconSize: 80,
showIconBackground: true,
iconBackgroundColor: Colors.indigo.withValues(alpha: 0.1),
title: 'Fully Customizable',
description: 'Customize colors, fonts, spacing, and more with EmptyViewStyle',
buttonText: 'Primary Action',
onButtonTap: () {},
secondaryButtonText: 'Secondary Action',
onSecondaryButtonTap: () {},
animationType: EmptyViewAnimation.slideUp,
style: EmptyViewStyle(
titleStyle: GoogleFonts.plusJakartaSans(
fontSize: 26,
fontWeight: FontWeight.w800,
color: Colors.indigo,
letterSpacing: -0.5,
),
descriptionStyle: GoogleFonts.poppins(
fontSize: 15,
fontWeight: FontWeight.w400,
color: Colors.grey.shade600,
height: 1.5,
),
buttonTextStyle: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w600,
),
buttonColor: Colors.indigo,
buttonBorderRadius: 25,
buttonHeight: 52,
secondaryButtonColor: Colors.indigo,
),
),
);
}
}
// ============ GRADIENT DEMO (NEW in v2.1) ============
class GradientDemo extends StatefulWidget {
const GradientDemo({super.key});
@override
State<GradientDemo> createState() => _GradientDemoState();
}
class _GradientDemoState extends State<GradientDemo> {
int _currentGradient = 0;
final List<_GradientOption> _gradients = [
_GradientOption(
'Sunset',
LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Colors.orange.shade100, Colors.pink.shade100],
),
),
_GradientOption(
'Ocean',
LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Colors.blue.shade100, Colors.cyan.shade50],
),
),
_GradientOption(
'Forest',
LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Colors.green.shade100, Colors.teal.shade50],
),
),
_GradientOption(
'Lavender',
LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Colors.purple.shade100, Colors.indigo.shade50],
),
),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Gradient Backgrounds')),
body: Column(
children: [
Expanded(
child: EmptyView(
key: ValueKey(_currentGradient),
icon: Icons.gradient,
iconColor: Colors.deepPurple,
iconSize: 80,
showIconBackground: true,
iconBackgroundColor: Colors.white,
title: 'Beautiful Gradients',
description: 'Add stunning gradient backgrounds to your empty states',
buttonText: 'Get Started',
onButtonTap: () {},
animationType: EmptyViewAnimation.fadeIn,
style: EmptyViewStyle.gradient(
gradient: _gradients[_currentGradient].gradient,
borderRadius: BorderRadius.circular(24),
buttonColor: Colors.deepPurple,
),
),
),
SafeArea(
child: Container(
padding: const EdgeInsets.all(20),
child: Wrap(
spacing: 8,
runSpacing: 8,
alignment: WrapAlignment.center,
children: List.generate(_gradients.length, (i) {
return ChoiceChip(
label: Text(_gradients[i].name),
selected: _currentGradient == i,
onSelected: (_) => setState(() => _currentGradient = i),
);
}),
),
),
),
],
),
);
}
}
class _GradientOption {
final String name;
final Gradient gradient;
_GradientOption(this.name, this.gradient);
}
// ============ BUILDER DEMO (NEW in v2.1) ============
class BuilderDemo extends StatefulWidget {
const BuilderDemo({super.key});
@override
State<BuilderDemo> createState() => _BuilderDemoState();
}
class _BuilderDemoState extends State<BuilderDemo> {
bool _animationComplete = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Builder Pattern')),
body: EmptyView.builder(
description: 'Create fully custom layouts with the builder pattern',
title: 'Custom Layout',
builder: (context, style) => Column(
mainAxisSize: MainAxisSize.min,
children: [
// Custom animated icon container
TweenAnimationBuilder<double>(
tween: Tween(begin: 0.0, end: 1.0),
duration: const Duration(milliseconds: 800),
builder: (context, value, child) => Transform.scale(
scale: value,
child: child,
),
child: Container(
width: 120,
height: 120,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Colors.cyan.shade400, Colors.blue.shade600],
),
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.blue.withValues(alpha: 0.3),
blurRadius: 20,
offset: const Offset(0, 10),
),
],
),
child: const Icon(
Icons.rocket_launch_rounded,
size: 56,
color: Colors.white,
),
),
),
const SizedBox(height: 24),
// Custom status indicator
if (_animationComplete)
Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Colors.green.shade100,
borderRadius: BorderRadius.circular(20),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.check_circle, size: 16, color: Colors.green.shade700),
const SizedBox(width: 6),
Text(
'Animation Complete!',
style: GoogleFonts.poppins(
color: Colors.green.shade700,
fontWeight: FontWeight.w600,
fontSize: 12,
),
),
],
),
),
],
),
buttonText: 'Launch App',
onButtonTap: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Launching...')),
);
},
secondaryButtonText: 'Learn More',
onSecondaryButtonTap: () {},
onAnimationComplete: () {
setState(() => _animationComplete = true);
},
animationType: EmptyViewAnimation.slideUp,
style: EmptyViewStyle(
titleStyle: GoogleFonts.plusJakartaSans(
fontSize: 24,
fontWeight: FontWeight.w800,
letterSpacing: -0.5,
),
descriptionStyle: GoogleFonts.poppins(
fontSize: 15,
color: Colors.grey.shade600,
height: 1.5,
),
buttonTextStyle: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w600,
),
buttonColor: Colors.blue.shade600,
buttonBorderRadius: 25,
),
),
);
}
}
// ============ REAL WORLD DEMO ============
class RealWorldDemo extends StatelessWidget {
const RealWorldDemo({super.key});
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 5,
child: Scaffold(
appBar: AppBar(
title: const Text('Real World Examples'),
bottom: const TabBar(
isScrollable: true,
tabs: [
Tab(text: 'E-Commerce'),
Tab(text: 'Social'),
Tab(text: 'Finance'),
Tab(text: 'Productivity'),
Tab(text: 'Auth'),
],
),
),
body: TabBarView(
children: [
// E-Commerce: Empty Cart
_buildEcommerceExample(),
// Social: Empty Feed
_buildSocialExample(),
// Finance: No Transactions
_buildFinanceExample(),
// Productivity: No Tasks
_buildProductivityExample(),
// Auth: Session Expired
_buildAuthExample(),
],
),
),
);
}
Widget _buildEcommerceExample() {
return EmptyView(
icon: Icons.shopping_bag_outlined,
iconColor: Colors.orange,
iconSize: 100,
showIconBackground: true,
iconBackgroundColor: Colors.orange.shade50,
title: 'Your Cart is Empty',
description: 'Looks like you haven\'t added anything to your cart yet. Start shopping to fill it up!',
buttonText: 'Browse Products',
onButtonTap: () {},
secondaryButtonText: 'View Wishlist',
onSecondaryButtonTap: () {},
animationType: EmptyViewAnimation.scale,
style: EmptyViewStyle(
titleStyle: GoogleFonts.plusJakartaSans(
fontSize: 24,
fontWeight: FontWeight.w800,
letterSpacing: -0.5,
),
descriptionStyle: GoogleFonts.poppins(
fontSize: 15,
color: Colors.grey.shade600,
height: 1.5,
),
buttonTextStyle: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w600,
),
buttonColor: Colors.orange,
buttonBorderRadius: 12,
secondaryButtonColor: Colors.orange,
),
);
}
Widget _buildSocialExample() {
return EmptyView.builder(
description: 'Follow some people to see their posts in your feed',
title: 'Your Feed is Empty',
builder: (context, style) => Column(
mainAxisSize: MainAxisSize.min,
children: [
Stack(
alignment: Alignment.center,
children: [
Container(
width: 100,
height: 100,
decoration: BoxDecoration(
color: Colors.blue.shade50,
shape: BoxShape.circle,
),
),
const Icon(
Icons.people_outline_rounded,
size: 60,
color: Colors.blue,
),
],
),
const SizedBox(height: 16),
// Suggested users
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(3, (i) => Container(
margin: const EdgeInsets.symmetric(horizontal: 4),
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.grey.shade200,
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 2),
),
child: Icon(Icons.person, size: 24, color: Colors.grey.shade400),
)),
),
],
),
buttonText: 'Find Friends',
onButtonTap: () {},
animationType: EmptyViewAnimation.fadeIn,
style: EmptyViewStyle(
titleStyle: GoogleFonts.plusJakartaSans(
fontSize: 24,
fontWeight: FontWeight.w800,
letterSpacing: -0.5,
),
descriptionStyle: GoogleFonts.poppins(
fontSize: 15,
color: Colors.grey.shade600,
height: 1.5,
),
buttonTextStyle: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w600,
),
buttonColor: Colors.blue,
buttonBorderRadius: 25,
),
);
}
Widget _buildFinanceExample() {
return EmptyView(
icon: Icons.account_balance_wallet_outlined,
iconColor: Colors.green.shade700,
iconSize: 90,
showIconBackground: true,
iconBackgroundColor: Colors.green.shade50,
title: 'No Transactions Yet',
description: 'Your transaction history will appear here once you make your first payment or transfer.',
buttonText: 'Add Money',
onButtonTap: () {},
secondaryButtonText: 'Link Bank Account',
onSecondaryButtonTap: () {},
animationType: EmptyViewAnimation.slideUp,
style: EmptyViewStyle(
backgroundGradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Colors.green.shade50, Colors.white],
),
titleStyle: GoogleFonts.plusJakartaSans(
fontSize: 24,
fontWeight: FontWeight.w800,
letterSpacing: -0.5,
),
descriptionStyle: GoogleFonts.poppins(
fontSize: 15,
color: Colors.grey.shade600,
height: 1.5,
),
buttonTextStyle: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w600,
),
buttonColor: Colors.green.shade700,
buttonBorderRadius: 12,
),
);
}
Widget _buildProductivityExample() {
return EmptyView(
icon: Icons.task_alt_rounded,
iconColor: Colors.purple,
iconSize: 90,
showIconBackground: true,
iconBackgroundColor: Colors.purple.shade50,
title: 'All Caught Up!',
description: 'You\'ve completed all your tasks. Take a break or add new tasks to stay productive.',
buttonText: 'Add New Task',
onButtonTap: () {},
animationType: EmptyViewAnimation.bounce,
style: EmptyViewStyle(
titleStyle: GoogleFonts.plusJakartaSans(
fontSize: 26,
fontWeight: FontWeight.w800,
color: Colors.purple.shade700,
letterSpacing: -0.5,
),
descriptionStyle: GoogleFonts.poppins(
fontSize: 15,
color: Colors.grey.shade600,
height: 1.5,
),
buttonTextStyle: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w600,
),
buttonColor: Colors.purple,
buttonBorderRadius: 16,
),
);
}
Widget _buildAuthExample() {
return EmptyViewPresets.sessionExpired(
onLogin: () {},
title: 'Session Expired',
description: 'Your session has timed out for security reasons. Please log in again to continue.',
style: EmptyViewStyle(
titleStyle: GoogleFonts.plusJakartaSans(
fontSize: 24,
fontWeight: FontWeight.w800,
letterSpacing: -0.5,
),
descriptionStyle: GoogleFonts.poppins(
fontSize: 15,
color: Colors.grey.shade600,
height: 1.5,
),
buttonTextStyle: GoogleFonts.poppins(
fontSize: 16,
fontWeight: FontWeight.w600,
),
buttonColor: Colors.red.shade400,
buttonBorderRadius: 12,
),
);
}
}