← Back to Blog

Flutter BackdropFilter Localization: Blur and Visual Effects for Multilingual Apps

flutterbackdropfilterblurglassmorphismlocalizationmodals

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

  1. Use ClipRect appropriately: Always wrap BackdropFilter with ClipRect or ClipRRect to define the blur boundary
  2. Consider performance: Blur effects can be expensive - use reasonable sigma values
  3. Provide fallbacks: Some older devices may struggle with heavy blur
  4. Ensure text readability: Add background overlays for text on blurred areas
  5. Respect RTL layouts: Position elements correctly for bidirectional text
  6. Add semantic labels: Describe blurred states for accessibility
  7. Test on devices: Blur can look different across platforms
  8. Combine with opacity: Semi-transparent overlays enhance the glass effect
  9. Layer correctly: BackdropFilter only affects content behind it in the widget tree
  10. 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.