Flutter BackdropFilter Localization: Blur and Visual Effects for Multilingual Apps
BackdropFilter applies visual effects like blur, color filters, and transforms to the area behind a widget. When combined with localization, BackdropFilter creates sophisticated glass-morphism effects, frosted overlays, and depth-aware interfaces that enhance multilingual content presentation. This guide covers comprehensive strategies for localizing BackdropFilter widgets in Flutter multilingual applications.
Understanding BackdropFilter Localization
BackdropFilter widgets require localization for:
- Modal dialogs: Blurred backgrounds with localized content
- Navigation overlays: Frosted app bars and bottom sheets
- Image overlays: Text on images with readable blur effects
- Glass cards: Translucent cards with localized information
- Loading states: Blur overlays with localized status messages
- Focus indicators: Blurred surroundings highlighting content
Basic BackdropFilter with Localized Content
Start with a simple blur effect example:
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class LocalizedBackdropFilterDemo extends StatelessWidget {
const LocalizedBackdropFilterDemo({super.key});
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: [
// Background image
Image.network(
'https://picsum.photos/800/1200',
fit: BoxFit.cover,
),
// Blurred overlay area
Positioned(
bottom: 0,
left: 0,
right: 0,
child: ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 15, sigmaY: 15),
child: Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.2),
),
child: SafeArea(
top: false,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
l10n.welcomeTitle,
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Text(
l10n.welcomeDescription,
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
color: Colors.white.withOpacity(0.9),
),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
foregroundColor: Colors.black87,
),
child: Text(l10n.getStartedButton),
),
],
),
),
),
),
),
),
],
),
);
}
}
ARB File Structure for BackdropFilter
{
"welcomeTitle": "Welcome to Our App",
"@welcomeTitle": {
"description": "Welcome title on the landing page"
},
"welcomeDescription": "Discover amazing features with beautiful blur effects",
"getStartedButton": "Get Started"
}
Glass Morphism Card
Create a modern glass-morphism card with localized content:
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class LocalizedGlassCard extends StatelessWidget {
final String title;
final String description;
final IconData icon;
final VoidCallback? onTap;
const LocalizedGlassCard({
super.key,
required this.title,
required this.description,
required this.icon,
this.onTap,
});
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
final isRtl = Directionality.of(context) == TextDirection.rtl;
return Semantics(
label: l10n.glassCardAccessibility(title, description),
button: onTap != null,
child: GestureDetector(
onTap: onTap,
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: isRtl ? Alignment.topRight : Alignment.topLeft,
end: isRtl ? Alignment.bottomLeft : Alignment.bottomRight,
colors: [
Colors.white.withOpacity(0.3),
Colors.white.withOpacity(0.1),
],
),
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: Colors.white.withOpacity(0.3),
width: 1.5,
),
),
child: Row(
children: [
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.2),
borderRadius: BorderRadius.circular(12),
),
child: Icon(
icon,
color: Colors.white,
size: 28,
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4),
Text(
description,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Colors.white.withOpacity(0.8),
),
),
],
),
),
Icon(
isRtl ? Icons.chevron_left : Icons.chevron_right,
color: Colors.white.withOpacity(0.6),
),
],
),
),
),
),
),
);
}
}
class GlassCardDemo extends StatelessWidget {
const GlassCardDemo({super.key});
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Scaffold(
body: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFF6366F1),
Color(0xFF8B5CF6),
Color(0xFFEC4899),
],
),
),
child: SafeArea(
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
l10n.dashboardTitle,
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Text(
l10n.dashboardSubtitle,
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
color: Colors.white.withOpacity(0.8),
),
),
const SizedBox(height: 32),
Expanded(
child: ListView(
children: [
LocalizedGlassCard(
icon: Icons.analytics,
title: l10n.analyticsCardTitle,
description: l10n.analyticsCardDescription,
onTap: () {},
),
const SizedBox(height: 16),
LocalizedGlassCard(
icon: Icons.notifications,
title: l10n.notificationsCardTitle,
description: l10n.notificationsCardDescription,
onTap: () {},
),
const SizedBox(height: 16),
LocalizedGlassCard(
icon: Icons.settings,
title: l10n.settingsCardTitle,
description: l10n.settingsCardDescription,
onTap: () {},
),
],
),
),
],
),
),
),
),
);
}
}
Blurred Modal Dialog
Create an elegant modal with backdrop blur:
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class LocalizedBlurredModal extends StatelessWidget {
final String title;
final String message;
final VoidCallback? onConfirm;
final VoidCallback? onCancel;
const LocalizedBlurredModal({
super.key,
required this.title,
required this.message,
this.onConfirm,
this.onCancel,
});
static Future<bool?> show(
BuildContext context, {
required String title,
required String message,
}) {
return showGeneralDialog<bool>(
context: context,
barrierDismissible: true,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
barrierColor: Colors.transparent,
transitionDuration: const Duration(milliseconds: 300),
pageBuilder: (context, animation, secondaryAnimation) {
return LocalizedBlurredModal(
title: title,
message: message,
onConfirm: () => Navigator.of(context).pop(true),
onCancel: () => Navigator.of(context).pop(false),
);
},
transitionBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: animation,
child: child,
);
},
);
}
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
final isRtl = Directionality.of(context) == TextDirection.rtl;
return Material(
type: MaterialType.transparency,
child: Stack(
fit: StackFit.expand,
children: [
// Blurred background
GestureDetector(
onTap: onCancel,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 8, sigmaY: 8),
child: Container(
color: Colors.black.withOpacity(0.3),
),
),
),
// Modal content
Center(
child: Semantics(
label: l10n.modalAccessibility(title),
child: Container(
margin: const EdgeInsets.all(32),
constraints: const BoxConstraints(maxWidth: 400),
child: ClipRRect(
borderRadius: BorderRadius.circular(24),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 20, sigmaY: 20),
child: Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface.withOpacity(0.85),
borderRadius: BorderRadius.circular(24),
border: Border.all(
color: Theme.of(context).colorScheme.outline.withOpacity(0.2),
),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 30,
offset: const Offset(0, 10),
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primaryContainer,
shape: BoxShape.circle,
),
child: Icon(
Icons.help_outline,
size: 32,
color: Theme.of(context).colorScheme.primary,
),
),
const SizedBox(height: 20),
Text(
title,
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 12),
Text(
message,
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 24),
Row(
children: [
Expanded(
child: OutlinedButton(
onPressed: onCancel,
style: OutlinedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16),
),
child: Text(l10n.cancelButton),
),
),
const SizedBox(width: 12),
Expanded(
child: ElevatedButton(
onPressed: onConfirm,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16),
),
child: Text(l10n.confirmButton),
),
),
],
),
],
),
),
),
),
),
),
),
],
),
);
}
}
Frosted App Bar
Create a frosted glass-style app bar:
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class LocalizedFrostedAppBar extends StatelessWidget implements PreferredSizeWidget {
final String title;
final List<Widget>? actions;
const LocalizedFrostedAppBar({
super.key,
required this.title,
this.actions,
});
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight + 20);
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 15, sigmaY: 15),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface.withOpacity(0.7),
border: Border(
bottom: BorderSide(
color: Theme.of(context).colorScheme.outline.withOpacity(0.1),
),
),
),
child: SafeArea(
bottom: false,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Row(
children: [
if (Navigator.of(context).canPop())
IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(),
tooltip: l10n.backButtonTooltip,
),
const SizedBox(width: 8),
Expanded(
child: Text(
title,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.w600,
),
),
),
if (actions != null) ...actions!,
],
),
),
),
),
),
);
}
}
class FrostedAppBarDemo extends StatelessWidget {
const FrostedAppBarDemo({super.key});
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Scaffold(
extendBodyBehindAppBar: true,
appBar: LocalizedFrostedAppBar(
title: l10n.galleryTitle,
actions: [
IconButton(
icon: const Icon(Icons.search),
onPressed: () {},
tooltip: l10n.searchTooltip,
),
IconButton(
icon: const Icon(Icons.more_vert),
onPressed: () {},
tooltip: l10n.moreOptionsTooltip,
),
],
),
body: GridView.builder(
padding: EdgeInsets.only(
top: MediaQuery.of(context).padding.top + kToolbarHeight + 36,
left: 8,
right: 8,
bottom: 8,
),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
),
itemCount: 20,
itemBuilder: (context, index) {
return ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Image.network(
'https://picsum.photos/400/400?random=$index',
fit: BoxFit.cover,
),
);
},
),
);
}
}
Loading Overlay with Blur
Create a loading state with blurred background:
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class LocalizedLoadingOverlay extends StatelessWidget {
final bool isLoading;
final Widget child;
final String? loadingMessage;
const LocalizedLoadingOverlay({
super.key,
required this.isLoading,
required this.child,
this.loadingMessage,
});
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Stack(
children: [
child,
if (isLoading)
Positioned.fill(
child: Semantics(
label: loadingMessage ?? l10n.loadingAccessibility,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: Container(
color: Colors.black.withOpacity(0.3),
child: Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 32,
vertical: 24,
),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface.withOpacity(0.8),
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: Theme.of(context).colorScheme.outline.withOpacity(0.2),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: 48,
height: 48,
child: CircularProgressIndicator(
strokeWidth: 3,
color: Theme.of(context).colorScheme.primary,
),
),
const SizedBox(height: 16),
Text(
loadingMessage ?? l10n.loadingMessage,
style: Theme.of(context).textTheme.bodyLarge,
textAlign: TextAlign.center,
),
],
),
),
),
),
),
),
),
),
),
],
);
}
}
class LoadingOverlayDemo extends StatefulWidget {
const LoadingOverlayDemo({super.key});
@override
State<LoadingOverlayDemo> createState() => _LoadingOverlayDemoState();
}
class _LoadingOverlayDemoState extends State<LoadingOverlayDemo> {
bool _isLoading = false;
String? _loadingMessage;
void _simulateLoading(String message) async {
setState(() {
_isLoading = true;
_loadingMessage = message;
});
await Future.delayed(const Duration(seconds: 2));
setState(() {
_isLoading = false;
_loadingMessage = null;
});
}
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return LocalizedLoadingOverlay(
isLoading: _isLoading,
loadingMessage: _loadingMessage,
child: Scaffold(
appBar: AppBar(title: Text(l10n.loadingDemoTitle)),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
l10n.loadingDemoDescription,
style: Theme.of(context).textTheme.bodyLarge,
),
const SizedBox(height: 24),
ElevatedButton.icon(
onPressed: () => _simulateLoading(l10n.savingData),
icon: const Icon(Icons.save),
label: Text(l10n.saveButton),
),
const SizedBox(height: 12),
ElevatedButton.icon(
onPressed: () => _simulateLoading(l10n.uploadingFile),
icon: const Icon(Icons.upload),
label: Text(l10n.uploadButton),
),
const SizedBox(height: 12),
ElevatedButton.icon(
onPressed: () => _simulateLoading(l10n.syncingData),
icon: const Icon(Icons.sync),
label: Text(l10n.syncButton),
),
],
),
),
),
);
}
}
Image with Text Overlay
Create readable text on images with blur:
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class LocalizedImageOverlay extends StatelessWidget {
final String imageUrl;
final String title;
final String subtitle;
final VoidCallback? onTap;
const LocalizedImageOverlay({
super.key,
required this.imageUrl,
required this.title,
required this.subtitle,
this.onTap,
});
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
final isRtl = Directionality.of(context) == TextDirection.rtl;
return Semantics(
label: l10n.imageOverlayAccessibility(title, subtitle),
button: onTap != null,
child: GestureDetector(
onTap: onTap,
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Stack(
children: [
// Background image
Positioned.fill(
child: Image.network(
imageUrl,
fit: BoxFit.cover,
),
),
// Gradient overlay for better text visibility
Positioned.fill(
child: DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.transparent,
Colors.black.withOpacity(0.7),
],
stops: const [0.5, 1.0],
),
),
),
),
// Blurred text area
Positioned(
bottom: 0,
left: 0,
right: 0,
child: ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 8, sigmaY: 8),
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.1),
),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: Colors.white,
fontWeight: FontWeight.bold,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 4),
Text(
subtitle,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: Colors.white.withOpacity(0.8),
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
if (onTap != null) ...[
const SizedBox(width: 12),
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.2),
shape: BoxShape.circle,
),
child: Icon(
isRtl ? Icons.arrow_back : Icons.arrow_forward,
color: Colors.white,
size: 20,
),
),
],
],
),
),
),
),
),
],
),
),
),
);
}
}
class ImageOverlayDemo extends StatelessWidget {
const ImageOverlayDemo({super.key});
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Scaffold(
appBar: AppBar(title: Text(l10n.imageOverlayDemoTitle)),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
SizedBox(
height: 200,
child: LocalizedImageOverlay(
imageUrl: 'https://picsum.photos/800/400?random=1',
title: l10n.articleTitle1,
subtitle: l10n.articleSubtitle1,
onTap: () {},
),
),
const SizedBox(height: 16),
SizedBox(
height: 200,
child: LocalizedImageOverlay(
imageUrl: 'https://picsum.photos/800/400?random=2',
title: l10n.articleTitle2,
subtitle: l10n.articleSubtitle2,
onTap: () {},
),
),
const SizedBox(height: 16),
SizedBox(
height: 200,
child: LocalizedImageOverlay(
imageUrl: 'https://picsum.photos/800/400?random=3',
title: l10n.articleTitle3,
subtitle: l10n.articleSubtitle3,
onTap: () {},
),
),
],
),
);
}
}
Spotlight Focus Effect
Create a spotlight effect that blurs surroundings:
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class LocalizedSpotlightFocus extends StatefulWidget {
final List<SpotlightItem> items;
const LocalizedSpotlightFocus({
super.key,
required this.items,
});
@override
State<LocalizedSpotlightFocus> createState() => _LocalizedSpotlightFocusState();
}
class _LocalizedSpotlightFocusState extends State<LocalizedSpotlightFocus> {
int? _focusedIndex;
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
return Scaffold(
appBar: AppBar(title: Text(l10n.spotlightDemoTitle)),
body: Stack(
children: [
// Main content grid
Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
l10n.spotlightInstructions,
style: Theme.of(context).textTheme.bodyLarge,
),
const SizedBox(height: 24),
Expanded(
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 16,
mainAxisSpacing: 16,
),
itemCount: widget.items.length,
itemBuilder: (context, index) {
final item = widget.items[index];
return GestureDetector(
onTap: () {
setState(() {
_focusedIndex = _focusedIndex == index ? null : index;
});
},
child: Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
item.icon,
size: 40,
color: Theme.of(context).colorScheme.primary,
),
const SizedBox(height: 12),
Text(
item.title,
style: Theme.of(context).textTheme.titleMedium,
textAlign: TextAlign.center,
),
],
),
),
),
);
},
),
),
],
),
),
// Blur overlay when focused
if (_focusedIndex != null)
Positioned.fill(
child: GestureDetector(
onTap: () => setState(() => _focusedIndex = null),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: Container(
color: Colors.black.withOpacity(0.5),
child: Center(
child: Semantics(
label: l10n.spotlightFocusAccessibility(
widget.items[_focusedIndex!].title,
),
child: Container(
margin: const EdgeInsets.all(32),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 15, sigmaY: 15),
child: Container(
padding: const EdgeInsets.all(32),
decoration: BoxDecoration(
color: Theme.of(context)
.colorScheme
.surface
.withOpacity(0.9),
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: Theme.of(context)
.colorScheme
.outline
.withOpacity(0.2),
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
widget.items[_focusedIndex!].icon,
size: 64,
color: Theme.of(context).colorScheme.primary,
),
const SizedBox(height: 20),
Text(
widget.items[_focusedIndex!].title,
style: Theme.of(context).textTheme.headlineSmall,
textAlign: TextAlign.center,
),
const SizedBox(height: 12),
Text(
widget.items[_focusedIndex!].description,
style: Theme.of(context).textTheme.bodyLarge,
textAlign: TextAlign.center,
),
const SizedBox(height: 24),
ElevatedButton(
onPressed: () =>
setState(() => _focusedIndex = null),
child: Text(l10n.closeButton),
),
],
),
),
),
),
),
),
),
),
),
),
),
],
),
);
}
}
class SpotlightItem {
final IconData icon;
final String title;
final String description;
SpotlightItem({
required this.icon,
required this.title,
required this.description,
});
}
Complete ARB File for BackdropFilter
{
"@@locale": "en",
"welcomeTitle": "Welcome to Our App",
"welcomeDescription": "Discover amazing features with beautiful blur effects",
"getStartedButton": "Get Started",
"glassCardAccessibility": "{title}: {description}",
"@glassCardAccessibility": {
"placeholders": {
"title": {"type": "String"},
"description": {"type": "String"}
}
},
"dashboardTitle": "Dashboard",
"dashboardSubtitle": "Your personalized overview",
"analyticsCardTitle": "Analytics",
"analyticsCardDescription": "View detailed insights and reports",
"notificationsCardTitle": "Notifications",
"notificationsCardDescription": "3 new messages waiting for you",
"settingsCardTitle": "Settings",
"settingsCardDescription": "Customize your experience",
"modalAccessibility": "Dialog: {title}",
"@modalAccessibility": {
"placeholders": {
"title": {"type": "String"}
}
},
"cancelButton": "Cancel",
"confirmButton": "Confirm",
"galleryTitle": "Photo Gallery",
"searchTooltip": "Search photos",
"moreOptionsTooltip": "More options",
"backButtonTooltip": "Go back",
"loadingAccessibility": "Loading content, please wait",
"loadingMessage": "Loading...",
"loadingDemoTitle": "Loading Overlay Demo",
"loadingDemoDescription": "Tap any button to see the loading overlay with blur effect",
"savingData": "Saving your data...",
"uploadingFile": "Uploading file...",
"syncingData": "Syncing with server...",
"saveButton": "Save Data",
"uploadButton": "Upload File",
"syncButton": "Sync Now",
"imageOverlayAccessibility": "{title}. {subtitle}",
"@imageOverlayAccessibility": {
"placeholders": {
"title": {"type": "String"},
"subtitle": {"type": "String"}
}
},
"imageOverlayDemoTitle": "Featured Articles",
"articleTitle1": "Getting Started with Flutter",
"articleSubtitle1": "Learn the basics of building cross-platform apps",
"articleTitle2": "Advanced UI Techniques",
"articleSubtitle2": "Master blur effects and glass morphism",
"articleTitle3": "Localization Best Practices",
"articleSubtitle3": "Build apps for a global audience",
"spotlightDemoTitle": "Feature Spotlight",
"spotlightInstructions": "Tap any item to focus on it with a spotlight effect",
"spotlightFocusAccessibility": "Focused on {item}",
"@spotlightFocusAccessibility": {
"placeholders": {
"item": {"type": "String"}
}
},
"closeButton": "Close"
}
Best Practices Summary
- Use ClipRect appropriately: Always wrap BackdropFilter with ClipRect or ClipRRect to define the blur boundary
- Consider performance: Blur effects can be expensive - use reasonable sigma values
- Provide fallbacks: Some older devices may struggle with heavy blur
- Ensure text readability: Add background overlays for text on blurred areas
- Respect RTL layouts: Position elements correctly for bidirectional text
- Add semantic labels: Describe blurred states for accessibility
- Test on devices: Blur can look different across platforms
- Combine with opacity: Semi-transparent overlays enhance the glass effect
- Layer correctly: BackdropFilter only affects content behind it in the widget tree
- Animate smoothly: When showing/hiding blur, use fade transitions
Conclusion
BackdropFilter creates sophisticated glass-morphism and frosted effects that elevate your app's visual design. When combined with localization, these effects help present multilingual content in elegant, readable ways. The key is balancing visual appeal with performance and accessibility, ensuring that blurred elements enhance rather than obstruct the user experience across all languages and devices.
Remember to test blur effects thoroughly across different devices and screen sizes, and always provide semantic labels that describe the current state for users relying on accessibility features.