context_curtain 1.1.5 copy "context_curtain: ^1.1.5" to clipboard
context_curtain: ^1.1.5 copied to clipboard

A premium UI/UX widget that creates an organic, physics-based canvas flutter animation for high-end features and menu reveals.

example/lib/main.dart

import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:context_curtain/curtain_flutter.dart';

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

/// Root app shell for the package demonstration application workspace.
class CurtainPackageExampleApp extends StatelessWidget {
  /// Default constructor for root app.
  const CurtainPackageExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Context Curtain Stress Engine',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        useMaterial3: true,
        brightness: Brightness.dark,
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.redAccent,
          brightness: Brightness.dark,
        ),
      ),
      home: const ExampleShowcaseScreen(),
    );
  }
}

/// Demo presentation showcase environment screen with heavy performance overlays.
class ExampleShowcaseScreen extends StatefulWidget {
  /// Default constructor for screen component.
  const ExampleShowcaseScreen({super.key});

  @override
  State<ExampleShowcaseScreen> createState() => _ExampleShowcaseScreenState();
}

class _ExampleShowcaseScreenState extends State<ExampleShowcaseScreen> {
  // Decentralized controllers managing isolated animation layer spaces
  final CurtainController _slideOneController = CurtainController();
  final CurtainController _slideTwoController = CurtainController();

  int _currentSlideIndex = 0;
  bool _isStressLoopActive = false;
  Ticker? _stressTicker;

  @override
  void dispose() {
    _stressTicker?.dispose();
    _slideOneController.dispose();
    _slideTwoController.dispose();
    super.dispose();
  }

  /// Toggles an aggressive programmatic animation loop to test pipeline stability 
  /// under violent, high-frequency layout mutations.
  void _toggleStressLoop() {
    setState(() {
      _isStressLoopActive = !_isStressLoopActive;
    });

    if (_isStressLoopActive) {
      int ticks = 0;
      _stressTicker = Ticker((elapsed) {
        ticks++;
        // Rapidly oscillate state triggers every 45 frames
        if (ticks % 45 == 0) {
          final nextTarget = (_currentSlideIndex + 1) % 3;
          _navigateTo(nextTarget);
        }
      });
      _stressTicker!.start();
    } else {
      _stressTicker?.stop();
      _stressTicker = null;
    }
  }

  /// Centralized state routing processor that resolves index modifications 
  /// sequentially across nested layouts without frame-skip artifacts.
  void _navigateTo(int index) {
    if (index == _currentSlideIndex && !_isStressLoopActive) return;

    setState(() => _currentSlideIndex = index);

    // Cascading logical transitions to safeguard against layout timeline clashes
    if (index == 0) {
      _slideTwoController.close();
      _slideOneController.close();
    } else if (index == 1) {
      _slideOneController.reveal();
      _slideTwoController.close();
    } else if (index == 2) {
      _slideOneController.reveal();
      _slideTwoController.reveal();
    }
  }

  void _next() {
    if (_currentSlideIndex < 2) _navigateTo(_currentSlideIndex + 1);
  }

  void _back() {
    if (_currentSlideIndex > 0) _navigateTo(_currentSlideIndex - 1);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: Stack(
        children: [
          /// =================================================================
          /// CURTAIN NESTING CASCADE STRESS ENGINE
          /// =================================================================
          CurtainReveal(
            controller: _slideOneController,
            side: CurtainSide.right, 
            curtainColor: const Color(0xFF1E1B4B), // Deep Slate/Indigo
            elevation: 40,
            revealedBackground: CurtainReveal(
              controller: _slideTwoController,
              side: CurtainSide.bottom, 
              curtainColor: const Color(0xFF0F172A), // Deep Charcoal
              elevation: 40,
              
              // SLIDE LAYER 03: Vector Field Noise System (Heavy Custom Paint Rendering)
              revealedBackground: _buildStressSlide(
                "03 / VECTOR FLUID",
                "Matrix Particle Core",
                Colors.greenAccent,
                const ParticleStressBackground(color: Colors.greenAccent),
              ),
              
              // SLIDE LAYER 02: Math Transform Grid System (Heavy Layout Math Layout)
              child: _buildStressSlide(
                "02 / RENDER BLOCK",
                "Dynamic Matrix Fields",
                Colors.cyanAccent,
                const RotatingMatrixStressBackground(),
              ),
            ),
            
            // SLIDE LAYER 01: Default Home Layout Cover
            child: _buildStressSlide(
              "01 / SANDBOX CORE",
              "Pipeline Stress Shell",
              Colors.amberAccent,
              const ParticleStressBackground(color: Colors.amberAccent),
            ),
          ),

          /// =================================================================
          /// TOP COMPONENT: ANCHOR POPUP INDEX DROPDOWN SHORTCUTS MENU
          /// =================================================================
          Positioned(
            top: 0,
            left: 0,
            right: 0,
            child: SafeArea(
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 8.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Row(
                      children: [
                        const Text(
                          "CURTAIN STRESS ENGINE",
                          style: TextStyle(
                            fontWeight: FontWeight.w900, 
                            letterSpacing: 2.0, 
                            fontSize: 12,
                          ),
                        ),
                        const SizedBox(width: 8),
                        _PerformanceTag(isActive: _isStressLoopActive),
                      ],
                    ),

                    PopupMenuButton<int>(
                      tooltip: "Jump directly to structural index",
                      icon: const CircleAvatar(
                        backgroundColor: Colors.black54,
                        child: Icon(Icons.apps_rounded, color: Colors.white, size: 20),
                      ),
                      onSelected: _navigateTo,
                      itemBuilder: (context) => [
                        const PopupMenuItem(value: 0, child: Text("Slide 1: Engine Core")),
                        const PopupMenuItem(value: 1, child: Text("Slide 2: Matrix Grid")),
                        const PopupMenuItem(value: 2, child: Text("Slide 3: Fluid Fields")),
                      ],
                    ),
                  ],
                ),
              ),
            ),
          ),

          /// =================================================================
          /// BOTTOM COMPONENT: PERSISTENT SYNCED FLOATING NAV PANEL
          /// =================================================================
          Positioned(
            bottom: 36,
            left: 24,
            right: 24,
            child: Center(
              child: Container(
                padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
                decoration: BoxDecoration(
                  color: Colors.black.withValues(alpha: 0.85),
                  borderRadius: BorderRadius.circular(24),
                  border: Border.all(color: Colors.white10),
                ),
                child: Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    IconButton(
                      onPressed: _currentSlideIndex > 0 ? _back : null,
                      icon: const Icon(Icons.arrow_back_ios_new, size: 14),
                      tooltip: "Previous Slide",
                    ),
                    const SizedBox(width: 12),
                    Text(
                      "SLIDE ${_currentSlideIndex + 1} / 3",
                      style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 13, letterSpacing: 1.0),
                    ),
                    const SizedBox(width: 12),
                    IconButton(
                      onPressed: _currentSlideIndex < 2 ? _next : null,
                      icon: const Icon(Icons.arrow_forward_ios, size: 14),
                      tooltip: "Next Slide",
                    ),
                    const SizedBox(width: 8),
                    const VerticalDivider(color: Colors.white24, width: 1, indent: 8, endIndent: 8),
                    const SizedBox(width: 8),
                    
                    // Core Stress-Testing Run Button Trigger
                    ElevatedButton.icon(
                      onPressed: _toggleStressLoop,
                      icon: Icon(
                        _isStressLoopActive ? Icons.stop_circle_rounded : Icons.bolt_rounded,
                        size: 16,
                        color: Colors.white,
                      ),
                      label: Text(_isStressLoopActive ? "STOP" : "STRESS TEST"),
                      style: ElevatedButton.styleFrom(
                        backgroundColor: _isStressLoopActive ? const Color.fromARGB(255, 160, 18, 8) : Colors.redAccent.withValues(alpha: 0.3),
                        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 0),
                        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

  /// Complex blueprint helper that weaves animation heavy testing modules behind layout texts
  Widget _buildStressSlide(String title, String subtitle, Color accent, Widget performanceBackground) {
    return Stack(
      fit: StackFit.expand,
      children: [
        // Heavy background background calculation engine pass
        performanceBackground,
        Container(
          color: Colors.black.withValues(alpha: 0.4), // Darken layer to protect reading visibility
        ),
        SafeArea(
          child: Padding(
            padding: const EdgeInsets.all(40),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                const Spacer(),
                Icon(Icons.layers, size: 64, color: accent),
                const SizedBox(height: 24),
                Text(
                  title,
                  style: TextStyle(color: accent, fontWeight: FontWeight.bold, letterSpacing: 3.5, fontSize: 13),
                ),
                const SizedBox(height: 8),
                Text(
                  subtitle,
                  style: const TextStyle(fontSize: 36, fontWeight: FontWeight.bold, letterSpacing: -1.0, height: 1.1),
                ),
                const SizedBox(height: 12),
                const Text(
                  "Executing real-time graphics pipelines underneath this stack layout sheet. Use multi-touch gestures directly on the cloth borders to verify frame rates.",
                  style: TextStyle(color: Colors.white60, fontSize: 14, height: 1.4),
                ),
                const Spacer(),
              ],
            ),
          ),
        ),
      ],
    );
  }
}

/// Helper tag indicating execution status state
class _PerformanceTag extends StatelessWidget {
  final bool isActive;
  const _PerformanceTag({required this.isActive});

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
      decoration: BoxDecoration(
        color: isActive ? Colors.red : Colors.green.withValues(alpha: 0.2),
        borderRadius: BorderRadius.circular(8),
      ),
      child: Text(
        isActive ? "LOOP ACTIVE (THRASHING)" : "STABLE",
        style: const TextStyle(fontSize: 9, fontWeight: FontWeight.bold, color: Colors.white),
      ),
    );
  }
}

/// =========================================================================
/// STRESS WORKLOAD MODULE 1: CUSTOM PAINTED PARTICLE SYSTEM FIELD
/// Forces high frequency canvas sweeps per paint invocation frame pass
/// =========================================================================
class ParticleStressBackground extends StatefulWidget {
  final Color color;
  const ParticleStressBackground({super.key, required this.color});

  @override
  State<ParticleStressBackground> createState() => _ParticleStressBackgroundState();
}

class _ParticleStressBackgroundState extends State<ParticleStressBackground> with SingleTickerProviderStateMixin {
  late List<_StressParticle> particles;
  late AnimationController _tickerController;
  final math.Random random = math.Random();

  @override
  void initState() {
    super.initState();
    // Spawns 120 isolated objects running spatial math loops
    particles = List.generate(120, (_) => _StressParticle(random));
    _tickerController = AnimationController(vsync: this, duration: const Duration(days: 1))..forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _tickerController,
      builder: (context, _) {
        for (var p in particles) {
          p.update();
        }
        return CustomPaint(
          painter: _ParticleFieldPainter(particles: particles, baseColor: widget.color),
        );
      },
    );
  }
}

class _StressParticle {
  late double x, y, vx, vy, size;
  final math.Random r;

  _StressParticle(this.r) {
    reset();
  }

  void reset() {
    x = r.nextDouble() * 400;
    y = r.nextDouble() * 800;
    vx = (r.nextDouble() - 0.5) * 2.5;
    vy = (r.nextDouble() - 0.5) * 2.5;
    size = r.nextDouble() * 4 + 2;
  }

  void update() {
    x += vx;
    y += vy;
    if (x < 0 || x > 500 || y < 0 || y > 900) reset();
  }
}

class _ParticleFieldPainter extends CustomPainter {
  final List<_StressParticle> particles;
  final Color baseColor;
  _ParticleFieldPainter({required this.particles, required this.baseColor});

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()..style = PaintingStyle.fill..isAntiAlias = false;
    for (var p in particles) {
      paint.color = baseColor.withValues(alpha: (p.size / 6).clamp(0.1, 0.6));
      canvas.drawCircle(Offset(p.x % size.width, p.y % size.height), p.size, paint);
    }
  }

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

/// =========================================================================
/// STRESS WORKLOAD MODULE 2: RECURSIVE MATRIX MATH DISPLAY GRID
/// Forces rendering matrix modifications down the layout layout tree
/// =========================================================================
class RotatingMatrixStressBackground extends StatefulWidget {
  const RotatingMatrixStressBackground({super.key});

  @override
  State<RotatingMatrixStressBackground> createState() => _RotatingMatrixStressBackgroundState();
}

class _RotatingMatrixStressBackgroundState extends State<RotatingMatrixStressBackground> with SingleTickerProviderStateMixin {
  late AnimationController _rotationController;

  @override
  void initState() {
    super.initState();
    _rotationController = AnimationController(vsync: this, duration: const Duration(seconds: 4))..repeat();
  }

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

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _rotationController,
      builder: (context, _) {
        return GridView.builder(
          physics: const NeverScrollableScrollPhysics(),
          gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 8),
          itemCount: 96,
          itemBuilder: (context, index) {
            final double angle = _rotationController.value * math.pi * 2 + (index * 0.1);
            return Transform(
              alignment: Alignment.center,
              transform: Matrix4.identity()
                ..setEntry(3, 2, 0.002)
                ..rotateX(angle)
                ..rotateY(angle * 0.5),
              child: Container(
                margin: const EdgeInsets.all(4),
                decoration: BoxDecoration(
                  color: Colors.cyanAccent.withValues(alpha: (math.sin(angle).abs() * 0.15).clamp(0.02, 0.2)),
                  border: Border.all(color: Colors.cyan.withValues(alpha: 0.2), width: 1),
                  borderRadius: BorderRadius.circular(4),
                ),
                child: const Center(
                  child: Icon(Icons.refresh_rounded, size: 12, color: Colors.cyanAccent),
                ),
              ),
            );
          },
        );
      },
    );
  }
}

// Extension to map custom color patterns on loop boundaries
extension on Colors {
}
3
likes
160
points
87
downloads

Documentation

API reference

Publisher

verified publishersamuelwangai.duckdns.org

Weekly Downloads

A premium UI/UX widget that creates an organic, physics-based canvas flutter animation for high-end features and menu reveals.

Repository (GitHub)

License

MIT (license)

Dependencies

flutter

More

Packages that depend on context_curtain