blurbox 0.0.5 copy "blurbox: ^0.0.5" to clipboard
blurbox: ^0.0.5 copied to clipboard

A Flutter package that applies a blur effect to its child widget.

example/lib/main.dart

import 'package:blurbox/blurbox.dart';
import 'package:flutter/material.dart';
import 'dart:math' as math;

void main() {
  runApp(const MyApp());
}

/// The main application widget.
///
/// Sets up the MaterialApp with appropriate themes and the home page.
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'BlurBox Examples',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.deepPurple,
          brightness: Brightness.light,
        ),
        useMaterial3: true,
      ),
      darkTheme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.deepPurple,
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
      ),
      themeMode: ThemeMode.system,
      home: const HomePage(),
    );
  }
}

/// The home page displaying a grid of example widgets.
///
/// Shows all available BlurBox examples in a grid layout.
class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      extendBody: true, // Allow content to go behind the bottom nav bar
      appBar: AppBar(
        forceMaterialTransparency: true,
        title: const Text('BlurBox Examples'),
        elevation: 0,
        backgroundColor: Colors.transparent,
        centerTitle: true,
        flexibleSpace: BlurBox(
          height: 210,
          blur: 8,
          color: Theme.of(context).colorScheme.primary.withValues(alpha: 0.1),
          borderRadius: const BorderRadius.only(
            bottomLeft: Radius.circular(16),
            bottomRight: Radius.circular(16),
          ),
          child: const SizedBox.shrink(),
        ),
      ),
      bottomNavigationBar: BlurBox(
        color: Theme.of(context).colorScheme.primary.withValues(alpha: 0.1),
        blur: 10,
        borderRadius: const BorderRadius.only(
          topLeft: Radius.circular(20),
          topRight: Radius.circular(20),
        ),
        child: Padding(
          padding: const EdgeInsets.only(top: 8, bottom: 8),
          child: Theme(
            data: Theme.of(context).copyWith(
              splashColor: Colors.transparent,
              highlightColor: Colors.transparent,
            ),
            child: BottomNavigationBar(
              type: BottomNavigationBarType.fixed,
              currentIndex: _selectedIndex,
              onTap: (index) {
                setState(() {
                  _selectedIndex = index;
                });
              },
              backgroundColor: Colors.transparent,
              elevation: 0,
              selectedItemColor: Theme.of(context).colorScheme.primary,
              unselectedItemColor: Theme.of(
                context,
              ).colorScheme.onSurface.withValues(alpha: 0.6),
              items: const [
                BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
                BottomNavigationBarItem(
                  icon: Icon(Icons.favorite),
                  label: 'Favorites',
                ),
                BottomNavigationBarItem(
                  icon: Icon(Icons.settings),
                  label: 'Settings',
                ),
              ],
            ),
          ),
        ),
      ),
      body: Stack(
        children: [
          // Vector Background
          const VectorBackground(),

          // Content
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: GridView.builder(
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2,
                crossAxisSpacing: 16,
                mainAxisSpacing: 16,
                childAspectRatio: 1.0,
              ),
              physics: const AlwaysScrollableScrollPhysics().applyTo(
                const BouncingScrollPhysics(),
              ),
              itemCount: exampleWidgets.length,
              itemBuilder: (context, index) {
                final example = exampleWidgets[index];
                return InkWell(
                  onTap:
                      () => Navigator.push(
                        context,
                        MaterialPageRoute(builder: (_) => example.builder()),
                      ),
                  borderRadius: BorderRadius.circular(16),
                  child: BlurBox(
                    blur: 5,
                    color: Theme.of(
                      context,
                    ).colorScheme.primary.withValues(alpha: 0.1),
                    borderRadius: BorderRadius.circular(16),
                    padding: const EdgeInsets.all(16),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(
                          example.icon,
                          size: 40,
                          color: Theme.of(context).colorScheme.primary,
                        ),
                        const SizedBox(height: 8),
                        Text(
                          example.title,
                          textAlign: TextAlign.center,
                          style: const TextStyle(fontWeight: FontWeight.bold),
                        ),
                      ],
                    ),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

// List of example widgets to display in the grid
final List<ExampleWidget> exampleWidgets = [
  ExampleWidget(
    title: 'Basic BlurBox',
    icon: Icons.blur_on,
    builder: () => const BasicBlurBoxExample(),
  ),
  ExampleWidget(
    title: 'Animated BlurBox',
    icon: Icons.animation,
    builder: () => const AnimatedBlurBoxExample(),
  ),
  ExampleWidget(
    title: 'Preset BlurBox',
    icon: Icons.style,
    builder: () => const PresetBlurBoxExample(),
  ),
  ExampleWidget(
    title: 'Themed BlurBox',
    icon: Icons.color_lens,
    builder: () => const ThemedBlurBoxExample(),
  ),
  ExampleWidget(
    title: 'Directional BlurBox',
    icon: Icons.gesture,
    builder: () => const DirectionalBlurBoxExample(),
  ),
  ExampleWidget(
    title: 'Radial BlurBox',
    icon: Icons.radio_button_checked,
    builder: () => const RadialBlurBoxExample(),
  ),
  ExampleWidget(
    title: 'Following BlurBox',
    icon: Icons.touch_app,
    builder: () => const FollowingBlurBoxExample(),
  ),
  ExampleWidget(
    title: 'Scroll Aware BlurBox',
    icon: Icons.roller_shades_closed_rounded,
    builder: () => const ScrollAwareBlurBoxExample(),
  ),
  ExampleWidget(
    title: 'PNG Pattern',
    icon: Icons.pattern,
    builder: () => const PngPatternedBlurBoxExample(),
  ),
  ExampleWidget(
    title: 'Geometric Pattern',
    icon: Icons.shape_line_rounded,
    builder: () => const GeometricPatternBlurBoxExample(),
  ),
  ExampleWidget(
    title: 'Organic Pattern',
    icon: Icons.bubble_chart,
    builder: () => const OrganicPatternBlurBoxExample(),
  ),
  ExampleWidget(
    title: 'Kaleidoscope',
    icon: Icons.auto_awesome,
    builder: () => const KaleidoscopeBlurBoxExample(),
  ),
  ExampleWidget(
    title: 'Extension Methods',
    icon: Icons.extension,
    builder: () => const ExtensionMethodsExample(),
  ),
];

/// Model class for example widgets displayed in the home grid.
///
/// Contains the title, icon, and builder function for each example.
class ExampleWidget {
  final String title;
  final IconData icon;
  final Widget Function() builder;

  const ExampleWidget({
    required this.title,
    required this.icon,
    required this.builder,
  });
}

/// A widget that provides a common layout for example pages.
///
/// Creates a scaffold with an app bar and a stack containing a vector
/// background and the provided child widget.
/// The app bar has a blurry background effect.
class ExamplePage extends StatelessWidget {
  final String title;
  final Widget child;

  const ExamplePage({super.key, required this.title, required this.child});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      appBar: AppBar(
        forceMaterialTransparency: true,
        title: Text(title),
        centerTitle: true,
        backgroundColor: Colors.transparent,
        elevation: 0,
        flexibleSpace: BlurBox(
          height: 210,
          blur: 8,
          color: Theme.of(context).colorScheme.primary.withValues(alpha: 0.1),
          borderRadius: const BorderRadius.only(
            bottomLeft: Radius.circular(16),
            bottomRight: Radius.circular(16),
          ),
          child: SizedBox.shrink(),
        ),
      ),
      body: Stack(
        children: [
          // Vector Background
          const VectorBackground(),

          // Content
          Padding(padding: const EdgeInsets.only(top: 70.0), child: child),
        ],
      ),
    );
  }
}

/// A decorative background widget that renders vector graphics.
///
/// Creates a full-size background with gradient colors and vector shapes.
/// Used to add visual interest to example pages.
class VectorBackground extends StatelessWidget {
  const VectorBackground({super.key});

  @override
  Widget build(BuildContext context) {
    return SizedBox.expand(
      child: CustomPaint(painter: VectorBackgroundPainter(context)),
    );
  }
}

/// Custom painter that renders a vector-based decorative background.
///
/// Creates a gradient background with various vector elements:
/// - Wave patterns at the bottom
/// - Floating geometric shapes
/// - Glowing dots for a cosmic effect
class VectorBackgroundPainter extends CustomPainter {
  final BuildContext context;

  VectorBackgroundPainter(this.context);

  @override
  void paint(Canvas canvas, Size size) {
    final rect = Offset.zero & size;
    final isDarkMode = Theme.of(context).brightness == Brightness.dark;

    // Create a theme-aware gradient background
    final Paint backgroundPaint =
        Paint()
          ..shader = LinearGradient(
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
            colors:
                isDarkMode
                    ? [
                      const Color(0xFF0F2027), // Dark teal
                      const Color(0xFF203A43), // Medium teal
                      const Color(0xFF2C5364), // Light teal
                    ]
                    : [
                      const Color(0xFFF0F8FF), // Alice blue
                      const Color(0xFFE6F2FF), // Light sky blue
                      const Color(0xFFD4E6FF), // Very light blue
                    ],
          ).createShader(rect);

    canvas.drawRect(rect, backgroundPaint);

    // Draw various vector shapes
    _drawWavePattern(canvas, size, isDarkMode);
    _drawFloatingShapes(canvas, size, isDarkMode);
    _drawGlowingDots(canvas, size, isDarkMode);
  }

  // Draw a wave pattern at the bottom
  void _drawWavePattern(Canvas canvas, Size size, bool isDarkMode) {
    final primaryWaveColor =
        isDarkMode
            ? const Color(0xFF5DE6DE).withValues(alpha: 0.15)
            : const Color(0xFF4287f5).withValues(alpha: 0.2);

    final secondaryWaveColor =
        isDarkMode
            ? const Color(0xFF5A8BFF).withValues(alpha: 0.1)
            : const Color(0xFF8A56AC).withValues(alpha: 0.15);

    final paint =
        Paint()
          ..color = primaryWaveColor
          ..style = PaintingStyle.fill;

    final wavePath = Path();
    wavePath.moveTo(0, size.height);

    // First wave
    for (double x = 0; x <= size.width; x += size.width / 20) {
      double y = size.height - 100 + 30 * math.sin(x * 0.05);
      wavePath.lineTo(x, y);
    }

    wavePath.lineTo(size.width, size.height);
    wavePath.close();
    canvas.drawPath(wavePath, paint);

    // Second wave (higher frequency)
    final wavePath2 = Path();
    wavePath2.moveTo(0, size.height);
    final paint2 =
        Paint()
          ..color = secondaryWaveColor
          ..style = PaintingStyle.fill;

    for (double x = 0; x <= size.width; x += size.width / 40) {
      double y = size.height - 50 + 20 * math.sin(x * 0.1);
      wavePath2.lineTo(x, y);
    }

    wavePath2.lineTo(size.width, size.height);
    wavePath2.close();
    canvas.drawPath(wavePath2, paint2);
  }

  // Draw floating geometric shapes
  void _drawFloatingShapes(Canvas canvas, Size size, bool isDarkMode) {
    final random = math.Random(42); // Fixed seed for consistency

    // Define theme-aware vibrant colors with transparency
    final colors =
        isDarkMode
            ? [
              const Color(0xFFFF61D2).withValues(alpha: 0.15), // Pink
              const Color(0xFFFE9090).withValues(alpha: 0.15), // Salmon
              const Color(0xFF7A66FF).withValues(alpha: 0.15), // Purple
              const Color(0xFF41C7FF).withValues(alpha: 0.15), // Blue
              const Color(0xFF41F1FF).withValues(alpha: 0.15), // Cyan
            ]
            : [
              const Color(0xFFE91E63).withValues(alpha: 0.25), // Pink
              const Color(0xFFFF5722).withValues(alpha: 0.2), // Deep Orange
              const Color(0xFF673AB7).withValues(alpha: 0.2), // Deep Purple
              const Color(0xFF2196F3).withValues(alpha: 0.25), // Blue
              const Color(0xFF009688).withValues(alpha: 0.2), // Teal
            ];

    // Draw hexagons
    for (int i = 0; i < 8; i++) {
      final centerX = random.nextDouble() * size.width;
      final centerY = random.nextDouble() * size.height * 0.7;
      final radius = 30.0 + random.nextDouble() * 50.0;

      final path = Path();
      for (int j = 0; j < 6; j++) {
        final angle = j * math.pi / 3;
        final x = centerX + radius * math.cos(angle);
        final y = centerY + radius * math.sin(angle);

        if (j == 0) {
          path.moveTo(x, y);
        } else {
          path.lineTo(x, y);
        }
      }
      path.close();

      final paint =
          Paint()
            ..color = colors[random.nextInt(colors.length)]
            ..style = PaintingStyle.fill;

      canvas.drawPath(path, paint);

      // Add a subtle stroke with theme-aware color
      final strokePaint =
          Paint()
            ..color = (isDarkMode ? Colors.white : Colors.black).withValues(
              alpha: 0.1,
            )
            ..style = PaintingStyle.stroke
            ..strokeWidth = 1.0;

      canvas.drawPath(path, strokePaint);
    }

    // Draw circles with gradients
    for (int i = 0; i < 12; i++) {
      final x = random.nextDouble() * size.width;
      final y = random.nextDouble() * size.height;
      final radius = 20.0 + random.nextDouble() * 40.0;

      final gradientPaint =
          Paint()
            ..shader = RadialGradient(
              colors: [
                colors[random.nextInt(colors.length)],
                colors[random.nextInt(colors.length)].withValues(alpha: 0.05),
              ],
            ).createShader(
              Rect.fromCircle(center: Offset(x, y), radius: radius),
            );

      canvas.drawCircle(Offset(x, y), radius, gradientPaint);
    }

    // Draw polygons
    for (int i = 0; i < 6; i++) {
      final centerX = random.nextDouble() * size.width;
      final centerY = random.nextDouble() * size.height;
      final radius = 20.0 + random.nextDouble() * 30.0;
      final sides = 3 + random.nextInt(3); // 3-5 sides

      final path = Path();
      for (int j = 0; j < sides; j++) {
        final angle = j * (2 * math.pi / sides);
        final x = centerX + radius * math.cos(angle);
        final y = centerY + radius * math.sin(angle);

        if (j == 0) {
          path.moveTo(x, y);
        } else {
          path.lineTo(x, y);
        }
      }
      path.close();

      final paint =
          Paint()
            ..color = colors[random.nextInt(colors.length)]
            ..style = PaintingStyle.fill;

      canvas.drawPath(path, paint);
    }
  }

  // Add glowing dots for a cosmic effect
  void _drawGlowingDots(Canvas canvas, Size size, bool isDarkMode) {
    final random = math.Random(24); // Different seed

    // Theme-aware glow colors
    final innerGlowColor =
        isDarkMode
            ? Colors.white.withValues(alpha: 0.6)
            : Colors.white.withValues(alpha: 0.7);

    final outerGlowColor =
        isDarkMode
            ? Colors.white.withValues(alpha: 0.15)
            : Colors.blue.withValues(alpha: 0.3);

    for (int i = 0; i < 60; i++) {
      final x = random.nextDouble() * size.width;
      final y = random.nextDouble() * size.height;
      final radius = 1.0 + random.nextDouble() * 2.5;

      // Inner glow
      final innerPaint = Paint()..color = innerGlowColor;

      // Outer glow
      final outerPaint =
          Paint()
            ..color = outerGlowColor
            ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 3.0);

      canvas.drawCircle(Offset(x, y), radius * 2, outerPaint);
      canvas.drawCircle(Offset(x, y), radius, innerPaint);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

//
// Individual example pages for each widget
//

/// Demonstrates the basic BlurBox widget with standard properties.
///
/// Shows a simple frosted glass effect card with custom styling.
class BasicBlurBoxExample extends StatelessWidget {
  const BasicBlurBoxExample({super.key});

  @override
  Widget build(BuildContext context) {
    return ExamplePage(
      title: 'Basic BlurBox',
      child: Center(
        child: BlurBox(
          blur: 10,
          color: Colors.white.withValues(alpha: 0.2),
          borderRadius: BorderRadius.circular(20),
          padding: const EdgeInsets.all(24),
          boxShadow: [
            BoxShadow(
              color: Colors.black.withValues(alpha: 0.2),
              blurRadius: 10,
              spreadRadius: 1,
            ),
          ],
          child: SizedBox(
            width: 300,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                const Icon(Icons.blur_on, size: 60),
                const SizedBox(height: 16),
                const Text(
                  'Basic BlurBox',
                  style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
                ),
                const SizedBox(height: 8),
                Text(
                  'A simple frosted glass effect with blur: 10, color: white(0.2)',
                  textAlign: TextAlign.center,
                  style: TextStyle(color: Colors.black.withValues(alpha: 0.7)),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

/// Demonstrates the AnimatedBlurBox with controllable blur transitions.
///
/// Allows toggling between blurred and clear states with animated transitions.
class AnimatedBlurBoxExample extends StatefulWidget {
  const AnimatedBlurBoxExample({super.key});

  @override
  State<AnimatedBlurBoxExample> createState() => _AnimatedBlurBoxExampleState();
}

class _AnimatedBlurBoxExampleState extends State<AnimatedBlurBoxExample> {
  bool _isBlurred = false;

  @override
  Widget build(BuildContext context) {
    return ExamplePage(
      title: 'Animated BlurBox',
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            AnimatedBlurBox(
              blur: _isBlurred ? 20.0 : 0.0,
              begin: _isBlurred ? 0.0 : 20.0,
              duration: const Duration(milliseconds: 800),
              curve: Curves.easeInOutCubic,
              borderRadius: BorderRadius.circular(20),
              color: Colors.white.withValues(alpha: 0.2),
              padding: const EdgeInsets.all(24),
              child: SizedBox(
                width: 300,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    const Icon(Icons.animation, size: 60),
                    const SizedBox(height: 16),
                    const Text(
                      'Animated BlurBox',
                      style: TextStyle(
                        fontSize: 24,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    const SizedBox(height: 8),
                    Text(
                      _isBlurred ? 'Blurred (20.0)' : 'Clear (0.0)',
                      textAlign: TextAlign.center,
                      style: const TextStyle(fontSize: 18),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 32),
            ElevatedButton.icon(
              onPressed: () {
                setState(() {
                  _isBlurred = !_isBlurred;
                });
              },
              icon: Icon(_isBlurred ? Icons.visibility : Icons.visibility_off),
              label: Text(_isBlurred ? 'Clear' : 'Blur'),
              style: ElevatedButton.styleFrom(
                padding: const EdgeInsets.symmetric(
                  horizontal: 32,
                  vertical: 16,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

/// Demonstrates the PresetBlurBox with various predefined blur styles.
///
/// Displays all available BlurPreset options in a scrollable list.
class PresetBlurBoxExample extends StatelessWidget {
  const PresetBlurBoxExample({super.key});

  @override
  Widget build(BuildContext context) {
    return ExamplePage(
      title: 'Preset BlurBox',
      child: Center(
        child: SingleChildScrollView(
          physics: const AlwaysScrollableScrollPhysics().applyTo(
            const BouncingScrollPhysics(),
          ),
          padding: const EdgeInsets.all(24),
          child: Column(
            children: [
              for (final preset in BlurPreset.values)
                Padding(
                  padding: const EdgeInsets.only(bottom: 16),
                  child: PresetBlurBox(
                    preset: preset,
                    borderRadius: BorderRadius.circular(16),
                    padding: const EdgeInsets.all(16),
                    child: Row(
                      children: [
                        const Icon(Icons.style, size: 36),
                        const SizedBox(width: 16),
                        Expanded(
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text(
                                preset.toString().split('.').last,
                                style: const TextStyle(
                                  fontSize: 18,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                              Text(
                                'A preset with predefined blur and style settings',
                                style: TextStyle(
                                  fontSize: 14,
                                  color: Colors.grey.shade700,
                                ),
                              ),
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
            ],
          ),
        ),
      ),
    );
  }
}

/// Demonstrates the ThemedBlurBox which adapts to the app's theme.
///
/// Shows a blur box that automatically uses appropriate colors from the theme.
class ThemedBlurBoxExample extends StatelessWidget {
  const ThemedBlurBoxExample({super.key});

  @override
  Widget build(BuildContext context) {
    return ExamplePage(
      title: 'Themed BlurBox',
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ThemedBlurBox(
              blur: 8,
              borderRadius: BorderRadius.circular(20),
              padding: const EdgeInsets.all(24),
              elevation: 4,
              child: SizedBox(
                width: 300,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    const Icon(Icons.color_lens, size: 60),
                    const SizedBox(height: 16),
                    const Text(
                      'Themed BlurBox',
                      style: TextStyle(
                        fontSize: 24,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    const SizedBox(height: 8),
                    const Text(
                      'Automatically adapts to your app theme colors',
                      textAlign: TextAlign.center,
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

/// Demonstrates the DirectionalBlurBox with adjustable blur direction.
///
/// Allows changing the angle of the blur effect using a slider.
class DirectionalBlurBoxExample extends StatefulWidget {
  const DirectionalBlurBoxExample({super.key});

  @override
  State<DirectionalBlurBoxExample> createState() =>
      _DirectionalBlurBoxExampleState();
}

class _DirectionalBlurBoxExampleState extends State<DirectionalBlurBoxExample> {
  double _angle = 45.0;

  @override
  Widget build(BuildContext context) {
    return ExamplePage(
      title: 'Directional BlurBox',
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            DirectionalBlurBox(
              blur: 12,
              angle: _angle,
              color: Colors.blue.withValues(alpha: 0.2),
              borderRadius: BorderRadius.circular(20),
              padding: const EdgeInsets.all(24),
              child: SizedBox(
                width: 300,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    const Icon(Icons.gesture, size: 60),
                    const SizedBox(height: 16),
                    const Text(
                      'Directional BlurBox',
                      style: TextStyle(
                        fontSize: 24,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    const SizedBox(height: 8),
                    Text(
                      'Blur angle: ${_angle.toStringAsFixed(0)}°',
                      textAlign: TextAlign.center,
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 24),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 48),
              child: Column(
                children: [
                  const Text('Adjust angle:'),
                  Slider(
                    value: _angle,
                    min: 0,
                    max: 360,
                    divisions: 72,
                    label: '${_angle.round()}°',
                    onChanged: (value) {
                      setState(() {
                        _angle = value;
                      });
                    },
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

/// Demonstrates the RadialBlurBox with a focal point that can be changed.
///
/// Shows blur that radiates from a focal point that can be controlled via touch.
class RadialBlurBoxExample extends StatefulWidget {
  const RadialBlurBoxExample({super.key});

  @override
  State<RadialBlurBoxExample> createState() => _RadialBlurBoxExampleState();
}

class _RadialBlurBoxExampleState extends State<RadialBlurBoxExample> {
  Alignment _focalPoint = Alignment.center;

  @override
  Widget build(BuildContext context) {
    return ExamplePage(
      title: 'Radial BlurBox',
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Expanded(
            child: GestureDetector(
              onPanUpdate: (details) {
                // Convert the touch position to an Alignment
                final RenderBox box = context.findRenderObject() as RenderBox;
                final Offset localPosition = box.globalToLocal(
                  details.globalPosition,
                );
                final double x = 2 * (localPosition.dx / box.size.width) - 1;
                final double y = 2 * (localPosition.dy / box.size.height) - 1;

                setState(() {
                  _focalPoint = Alignment(x, y);
                });
              },
              child: Center(
                child: RadialBlurBox(
                  radius: 150.0,
                  falloff: 2.0,
                  quality: 8,
                  maxBlur: 15,
                  focalPoint: _focalPoint,

                  color: Colors.purple.withValues(alpha: 0.2),
                  borderRadius: BorderRadius.circular(20),
                  padding: const EdgeInsets.all(24),
                  child: SizedBox(
                    width: 300,
                    height: 300,
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        const Icon(Icons.radio_button_checked, size: 60),
                        const SizedBox(height: 16),
                        const Text(
                          'Radial BlurBox',
                          style: TextStyle(
                            fontSize: 24,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                        const SizedBox(height: 8),
                        const Text(
                          'Tap or drag anywhere to move focal point',
                          textAlign: TextAlign.center,
                        ),
                        const SizedBox(height: 16),
                        Text(
                          'Focal point: (${_focalPoint.x.toStringAsFixed(2)}, ${_focalPoint.y.toStringAsFixed(2)})',
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            fontSize: 12,
                            color: Colors.grey.shade700,
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

/// Demonstrates the FollowingBlurBox that tracks user input.
///
/// Shows a blur effect that follows the user's finger or cursor.
class FollowingBlurBoxExample extends StatelessWidget {
  const FollowingBlurBoxExample({super.key});

  @override
  Widget build(BuildContext context) {
    return ExamplePage(
      title: 'Following BlurBox',
      child: Center(
        child: Padding(
          padding: const EdgeInsets.all(24.0),
          child: FollowingBlurBox(
            radius: 60,
            blurIntensity: 12,
            followSpeed: 0.5,
            color: Colors.pink.withValues(alpha: 0.2),
            child: Container(
              height: 400,
              width: double.infinity,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(20),
                border: Border.all(color: Colors.white.withValues(alpha: 0.2)),
              ),
              child: const Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Icon(Icons.touch_app, size: 60),
                  SizedBox(height: 16),
                  Text(
                    'Following BlurBox',
                    style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
                  ),
                  SizedBox(height: 8),
                  Text(
                    'Move your finger or cursor\nover this container',
                    textAlign: TextAlign.center,
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

/// Demonstrates the ScrollAwareBlurBox that responds to scroll position.
///
/// Shows a header that becomes more blurred as the user scrolls down.
class ScrollAwareBlurBoxExample extends StatefulWidget {
  const ScrollAwareBlurBoxExample({super.key});

  @override
  State<ScrollAwareBlurBoxExample> createState() =>
      _ScrollAwareBlurBoxExampleState();
}

class _ScrollAwareBlurBoxExampleState extends State<ScrollAwareBlurBoxExample> {
  final ScrollController _scrollController = ScrollController();

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return ExamplePage(
      title: 'ScrollAware BlurBox',
      child: Stack(
        children: [
          ListView.builder(
            physics: const AlwaysScrollableScrollPhysics().applyTo(
              const BouncingScrollPhysics(),
            ),
            controller: _scrollController,
            padding: const EdgeInsets.only(top: 150),
            itemCount: 50,
            itemBuilder: (context, index) {
              return ListTile(
                title: Text('Item $index'),
                subtitle: const Text('Scroll to change header blur'),
              );
            },
          ),
          Positioned(
            top: 0,
            left: 0,
            right: 0,
            child: ScrollAwareBlurBox(
              scrollController: _scrollController,
              minBlur: 0,
              maxBlur: 15,
              scrollThreshold: 300,
              color: Colors.white.withValues(alpha: 0.3),
              child: const SafeArea(
                bottom: false,
                child: Padding(
                  padding: EdgeInsets.all(16),
                  child: Row(
                    children: [
                      Icon(Icons.roller_shades_closed_rounded),
                      SizedBox(width: 12),
                      Expanded(
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              'ScrollAware BlurBox',
                              style: TextStyle(
                                fontWeight: FontWeight.bold,
                                fontSize: 18,
                              ),
                            ),
                            Text('Scroll down to increase blur effect'),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

/// Demonstrates the GeometricPatternBlurBox with abstract shapes.
///
/// Shows a blur box with generated geometric patterns and shapes.
class GeometricPatternBlurBoxExample extends StatelessWidget {
  const GeometricPatternBlurBoxExample({super.key});

  @override
  Widget build(BuildContext context) {
    return ExamplePage(
      title: 'Geometric Pattern',
      child: Center(
        child: Padding(
          padding: const EdgeInsets.all(24.0),
          child: GeometricPatternBlurBox(
            baseBlur: 8,
            shapeCount: 100,
            colors: [
              Colors.blue.withValues(alpha: 0.5),
              Colors.purple.withValues(alpha: 0.5),
              Colors.pink.withValues(alpha: 0.5),
            ],
            shapeTypes: const [
              GeometricShapeType.circle,
              GeometricShapeType.rectangle,
              GeometricShapeType.oval,
              GeometricShapeType.triangle,
            ],
            borderRadius: BorderRadius.circular(20),
            child: Container(
              width: double.infinity,
              height: 400,
              padding: const EdgeInsets.all(24),
              child: const Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Icon(Icons.shape_line_rounded, size: 60, color: Colors.white),
                  SizedBox(height: 16),
                  Text(
                    'Geometric Pattern',
                    style: TextStyle(
                      fontSize: 24,
                      fontWeight: FontWeight.bold,
                      color: Colors.white,
                    ),
                  ),
                  SizedBox(height: 8),
                  Text(
                    'Abstract geometric shapes with blur effects',
                    textAlign: TextAlign.center,
                    style: TextStyle(color: Colors.white),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

/// Demonstrates the OrganicPatternBlurBox with flowing patterns.
///
/// Shows natural, organic-looking animated blur patterns.
class OrganicPatternBlurBoxExample extends StatelessWidget {
  const OrganicPatternBlurBoxExample({super.key});

  @override
  Widget build(BuildContext context) {
    return ExamplePage(
      title: 'Organic Pattern',
      child: Center(
        child: Padding(
          padding: const EdgeInsets.all(24.0),
          child: OrganicPatternBlurBox(
            blur: 10,
            backgrundBlur: 50,
            color: Colors.teal.withValues(alpha: 0.4),
            complexity: 8,
            fluidity: 0.8,
            animationDuration: const Duration(seconds: 15),
            borderRadius: BorderRadius.circular(20),
            child: Container(
              width: double.infinity,
              height: 400,
              padding: const EdgeInsets.all(24),
              child: const Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Icon(Icons.bubble_chart, size: 60, color: Colors.white),
                  SizedBox(height: 16),
                  Text(
                    'Organic Pattern',
                    style: TextStyle(
                      fontSize: 24,
                      fontWeight: FontWeight.bold,
                      color: Colors.white,
                    ),
                  ),
                  SizedBox(height: 8),
                  Text(
                    'Flowing, natural blur patterns that animate over time',
                    textAlign: TextAlign.center,
                    style: TextStyle(color: Colors.white),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

/// Demonstrates the KaleidoscopeBlurBox with symmetrical patterns.
///
/// Shows a kaleidoscope effect using various pattern types with blur.
class KaleidoscopeBlurBoxExample extends StatefulWidget {
  const KaleidoscopeBlurBoxExample({super.key});

  @override
  State<KaleidoscopeBlurBoxExample> createState() =>
      _KaleidoscopeBlurBoxExampleState();
}

class _KaleidoscopeBlurBoxExampleState
    extends State<KaleidoscopeBlurBoxExample> {
  KaleidoscopePatternType _selectedPatternType = KaleidoscopePatternType.basic;
  bool _animated = true;

  @override
  Widget build(BuildContext context) {
    return ExamplePage(
      title: 'Kaleidoscope',
      child: Column(
        children: [
          Expanded(
            child: Center(
              child: Padding(
                padding: const EdgeInsets.all(24.0),
                child: KaleidoscopeBlurBox(
                  segments: 20,
                  blur: 5.0,
                  color: Colors.purple.withValues(alpha: 0.2),
                  animated: _animated,
                  patternType: _selectedPatternType,
                  rotationDuration: const Duration(seconds: 20),
                  borderRadius: BorderRadius.circular(20),
                  width: double.infinity,
                  height: 400,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      const Icon(
                        Icons.auto_awesome,
                        size: 60,
                        color: Colors.white,
                      ),
                      const SizedBox(height: 16),
                      const Text(
                        'Kaleidoscope BlurBox',
                        style: TextStyle(
                          fontSize: 24,
                          fontWeight: FontWeight.bold,
                          color: Colors.white,
                        ),
                      ),
                      const SizedBox(height: 8),
                      Text(
                        'Pattern type: ${_selectedPatternType.toString().split('.').last}',
                        textAlign: TextAlign.center,
                        style: const TextStyle(color: Colors.white),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ),

          // Pattern type selection
          Container(
            color: Colors.black12,
            padding: const EdgeInsets.all(16.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                const Text(
                  'Pattern Type:',
                  style: TextStyle(fontWeight: FontWeight.bold),
                ),
                const SizedBox(height: 8),
                SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: Row(
                    children: [
                      for (final patternType in KaleidoscopePatternType.values)
                        Padding(
                          padding: const EdgeInsets.only(right: 8.0),
                          child: ChoiceChip(
                            label: Text(patternType.toString().split('.').last),
                            selected: _selectedPatternType == patternType,
                            onSelected: (selected) {
                              if (selected) {
                                setState(() {
                                  _selectedPatternType = patternType;
                                });
                              }
                            },
                          ),
                        ),
                    ],
                  ),
                ),

                const SizedBox(height: 16),
                Row(
                  children: [
                    const Text(
                      'Animation:',
                      style: TextStyle(fontWeight: FontWeight.bold),
                    ),
                    const SizedBox(width: 8),
                    Switch(
                      value: _animated,
                      onChanged: (value) {
                        setState(() {
                          _animated = value;
                        });
                      },
                    ),
                  ],
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

/// Demonstrates the extension methods available for adding blur effects.
///
/// Shows how to use the .blurry() and .animatedBlurry() extensions on widgets.
class ExtensionMethodsExample extends StatefulWidget {
  const ExtensionMethodsExample({super.key});

  @override
  State<ExtensionMethodsExample> createState() =>
      _ExtensionMethodsExampleState();
}

class _ExtensionMethodsExampleState extends State<ExtensionMethodsExample> {
  bool _isBlurred = false;

  @override
  Widget build(BuildContext context) {
    return ExamplePage(
      title: 'Extension Methods',
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // Simple blurry extension
            Container(
              width: 300,
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  colors: [
                    Colors.blue.withValues(alpha: 0.1),
                    Colors.purple.withValues(alpha: 0.1),
                  ],
                ),
                borderRadius: BorderRadius.circular(16),
              ),
              child: const Column(
                children: [
                  Icon(Icons.extension, size: 40, color: Colors.white),
                  SizedBox(height: 8),
                  Text(
                    'Container with gradient',
                    style: TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ],
              ),
            ).blurry(
              blur: _isBlurred ? 10.0 : 0.0,
              borderRadius: BorderRadius.circular(16),
              padding: EdgeInsets.zero,
            ),

            const SizedBox(height: 24),

            // Animated blurry extension
            Container(
              width: 300,
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  colors: [
                    Colors.orange.withValues(alpha: 0.1),
                    Colors.red.withValues(alpha: 0.1),
                  ],
                ),
                borderRadius: BorderRadius.circular(16),
              ),
              child: const Column(
                children: [
                  Icon(Icons.animation, size: 40, color: Colors.white),
                  SizedBox(height: 8),
                  Text(
                    'With animated blur',
                    style: TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ],
              ),
            ).animatedBlurry(
              blur: _isBlurred ? 10.0 : 0.0,
              beginBlur: _isBlurred ? 0.0 : 10.0,
              duration: const Duration(milliseconds: 500),
              borderRadius: BorderRadius.circular(16),
              padding: EdgeInsets.zero,
            ),

            const SizedBox(height: 24),

            ElevatedButton.icon(
              onPressed: () {
                setState(() {
                  _isBlurred = !_isBlurred;
                });
              },
              icon: Icon(_isBlurred ? Icons.visibility : Icons.visibility_off),
              label: Text(_isBlurred ? 'Clear' : 'Blur'),
            ),
          ],
        ),
      ),
    );
  }
}

/// Demonstrates the PatternedBlurBox using a PNG pattern.
///
/// Shows how to use a PNG image as a pattern overlay with blur effects.
class PngPatternedBlurBoxExample extends StatelessWidget {
  const PngPatternedBlurBoxExample({super.key});

  @override
  Widget build(BuildContext context) {
    return ExamplePage(
      title: 'PNG Pattern BlurBox',
      child: Center(
        child: Padding(
          padding: const EdgeInsets.all(24.0),
          child: PatternedBlurBox(
            height: 500,
            blur: 8.0,
            color: Colors.white.withValues(alpha: 0.2),
            patternAsset: 'assets/images/vc_pattern.png',
            patternOpacity: 0.9,
            patternScale: 0.5,
            patternColor: Theme.of(context).colorScheme.primary,
            patternBlendMode: BlendMode.srcIn,
            borderRadius: BorderRadius.circular(20),
            padding: const EdgeInsets.all(24),
            child: SizedBox(
              width: double.infinity,
              height: 400,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Icon(Icons.pattern, size: 60),
                  const SizedBox(height: 16),
                  const Text(
                    'PNG Pattern BlurBox',
                    style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
                  ),
                  const SizedBox(height: 12),
                  Text(
                    'Using PNG pattern with opacity: 0.2, scale: 0.5',
                    textAlign: TextAlign.center,
                    style: TextStyle(color: Colors.grey.shade800),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}
14
likes
160
points
1.03k
downloads

Publisher

verified publisherox0.ir

Weekly Downloads

A Flutter package that applies a blur effect to its child widget.

Repository (GitHub)

Documentation

API reference

License

Apache-2.0 (license)

Dependencies

flutter

More

Packages that depend on blurbox