blurred_overlay 1.3.1
blurred_overlay: ^1.3.1 copied to clipboard
A lightweight Flutter package to show frosted glass AppBars, bottom navigation bars, blurred dialogs, modal bottom sheets, drawers, and loading overlays.
import 'dart:async';
import 'package:blurred_overlay/blurred_overlay.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Blurred Overlay Demo',
theme: ThemeData(useMaterial3: true, colorSchemeSeed: Colors.blue),
home: const DemoHomePage(),
);
}
}
class DemoHomePage extends StatefulWidget {
const DemoHomePage({super.key});
@override
State<DemoHomePage> createState() => _DemoHomePageState();
}
class _DemoHomePageState extends State<DemoHomePage> {
bool _isLoading = false;
bool _isProgressLoading = false;
double _progress = 0.0;
int _currentNavIndex = 0;
void _triggerLoadingOverlay() {
setState(() => _isLoading = true);
Future.delayed(const Duration(seconds: 2), () {
if (mounted) setState(() => _isLoading = false);
});
}
void _triggerProgressLoading() {
setState(() {
_isProgressLoading = true;
_progress = 0.0;
});
Timer.periodic(const Duration(milliseconds: 40), (timer) {
if (!mounted) {
timer.cancel();
return;
}
setState(() {
_progress += 2.5;
if (_progress >= 100.0) {
timer.cancel();
Future.delayed(const Duration(milliseconds: 300), () {
if (mounted) setState(() => _isProgressLoading = false);
});
}
});
});
}
@override
Widget build(BuildContext context) {
return BlurredLoadingOverlay(
isLoading: _isLoading,
loadingStyle: LoadingStyle.pulseRing,
headerWidget: const Text(
'Loading...',
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
footerWidget: const Text(
'Please wait a moment',
style: TextStyle(color: Colors.white70),
),
child: BlurredLoadingPercentage(
isLoading: _isProgressLoading,
progress: _progress,
progressStyle: ProgressStyle.circle,
headerWidget: const Text(
'Downloading Updates',
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
child: Scaffold(
extendBody: true,
extendBodyBehindAppBar: true,
appBar: const BlurredAppBar(
title: Text('Blurred Overlay Example'),
blurSigma: 12.0,
),
bottomNavigationBar: BlurredBottomNavigationBar(
currentIndex: _currentNavIndex,
onTap: (index) => setState(() => _currentNavIndex = index),
margin: const EdgeInsets.fromLTRB(16, 0, 16, 16),
borderRadius: BorderRadius.circular(24.0),
items: const [
BlurredNavItem(
icon: Icon(Icons.home_outlined),
activeIcon: Icon(Icons.home),
label: 'Home',
),
BlurredNavItem(
icon: Icon(Icons.layers_outlined),
activeIcon: Icon(Icons.layers),
label: 'Overlays',
),
BlurredNavItem(
icon: Icon(Icons.settings_outlined),
activeIcon: Icon(Icons.settings),
label: 'Settings',
),
],
),
drawer: BlurredDrawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
DrawerHeader(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primaryContainer,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Icon(
Icons.blur_on,
size: 48,
color: Theme.of(context).colorScheme.onPrimaryContainer,
),
const SizedBox(height: 8),
Text(
'Blurred Drawer',
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
color:
Theme.of(context).colorScheme.onPrimaryContainer,
),
),
],
),
),
ListTile(
leading: const Icon(Icons.home),
title: const Text('Home'),
onTap: () {
Navigator.pop(context);
},
),
ListTile(
leading: const Icon(Icons.settings),
title: const Text('Settings'),
onTap: () {
Navigator.pop(context);
},
),
ListTile(
leading: const Icon(Icons.person),
title: const Text('Profile'),
onTap: () {
Navigator.pop(context);
},
),
const Divider(),
ListTile(
leading: const Icon(Icons.info_outline),
title: const Text('About'),
onTap: () {
Navigator.pop(context);
},
),
ListTile(
leading: const Icon(Icons.logout),
title: const Text('Logout'),
onTap: () {
Navigator.pop(context);
},
),
],
),
),
body: SingleChildScrollView(
padding: EdgeInsets.only(
top: MediaQuery.of(context).padding.top + kToolbarHeight + 8,
bottom: 24,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(
Icons.phone_android_rounded,
color: Colors.blueAccent,
),
title: const Text('System Info (Modal Bottom Sheet)'),
subtitle: const Text('Show blurred modal bottom sheet with handle'),
onTap: () {
showBottomSheetDialog(context);
},
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
),
ListTile(
leading: Icon(
Icons.room_preferences_outlined,
color: Colors.redAccent[400],
),
title: const Text('Root Status (Dialog)'),
subtitle: const Text('Show blurred dialog'),
onTap: () {
showRootStatusDialog(context);
},
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
),
const Divider(),
ListTile(
leading: const Icon(
Icons.hourglass_top_rounded,
color: Colors.amber,
),
title: const Text('Test Loading Overlay'),
subtitle: const Text('Shows pulse ring loading animation with blur'),
onTap: _triggerLoadingOverlay,
trailing: const Icon(Icons.play_arrow),
),
ListTile(
leading: const Icon(
Icons.percent_rounded,
color: Colors.green,
),
title: const Text('Test Progress Loading'),
subtitle: const Text('Shows circular percentage animation with blur'),
onTap: _triggerProgressLoading,
trailing: const Icon(Icons.play_arrow),
),
const Divider(),
ListTile(
leading: Icon(Icons.wifi, color: Colors.greenAccent[400]),
title: const Text('Network & internet'),
onTap: () {},
),
ListTile(
leading: Icon(Icons.bluetooth, color: Colors.lightBlueAccent),
title: const Text('Connected devices'),
onTap: () {},
),
ListTile(
leading: Icon(Icons.notifications, color: Colors.orangeAccent),
title: const Text('Notifications'),
onTap: () {},
),
],
),
),
),
),
);
}
void showBottomSheetDialog(BuildContext context) {
showBlurredModalBottomSheet(
context: context,
showHandle: true,
builder: (context) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Padding(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: Text(
'System Information',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
const Divider(color: Colors.white24, indent: 20, endIndent: 20),
const InfoRow(
icon: Icons.devices,
label: 'Device Name',
value: 'Galaxy A50',
),
const InfoRow(
icon: Icons.developer_board,
label: 'Model',
value: 'Flutter G-24',
),
const InfoRow(icon: Icons.memory, label: 'RAM', value: '12 GB'),
const InfoRow(
icon: Icons.sd_storage,
label: 'ROM',
value: '256 GB',
),
const InfoRow(
icon: Icons.memory_rounded,
label: 'Chipset',
value: 'Tensor G4 Pro',
),
const InfoRow(
icon: Icons.android,
label: 'OS Version',
value: 'Android 15 (Vanilla)',
),
],
);
},
);
}
void showRootStatusDialog(BuildContext context) {
showBlurredDialog(
context: context,
builder: (context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text(
'Root Status',
style: TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
),
const SizedBox(height: 16.0),
const Text(
'Your phone Galaxy A50 is not rooted.',
textAlign: TextAlign.left,
style: TextStyle(fontSize: 16.0),
),
const SizedBox(height: 24.0),
Align(
alignment: Alignment.bottomRight,
child: TextButton(
onPressed: () {
Navigator.of(context).pop(); // Close the dialog
},
child: const Text('CLOSE'),
),
),
],
),
),
);
},
);
}
}
class InfoRow extends StatelessWidget {
final IconData icon;
final String label;
final String value;
const InfoRow({
super.key,
required this.icon,
required this.label,
required this.value,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 10.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(icon, size: 15),
const SizedBox(width: 10),
Expanded(child: Text(label, style: const TextStyle(fontSize: 14))),
Expanded(
flex: 1,
child: Text(
value,
textAlign: TextAlign.end,
style: const TextStyle(fontSize: 12),
),
),
],
),
);
}
}