coverflow_carousel 1.1.1 copy "coverflow_carousel: ^1.1.1" to clipboard
coverflow_carousel: ^1.1.1 copied to clipboard

A highly customizable 3D coverflow-style carousel for Flutter with smooth animations, perspective effects, and controller support.

example/lib/main.dart

// ignore_for_file: deprecated_member_use

import 'package:flutter/material.dart';
import 'package:coverflow_carousel/coverflow_carousel.dart';

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

class CoverflowCarouselExampleApp extends StatelessWidget {
  const CoverflowCarouselExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Coverflow Carousel Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        brightness: Brightness.dark,
        primaryColor: Colors.deepPurple,
        scaffoldBackgroundColor: const Color(0xFF0F0E17),
        colorScheme: const ColorScheme.dark(
          primary: Colors.deepPurple,
          secondary: Colors.pinkAccent,
        ),
      ),
      home: const CoverflowDemoScreen(),
    );
  }
}

class CoverflowDemoScreen extends StatefulWidget {
  const CoverflowDemoScreen({super.key});

  @override
  State<CoverflowDemoScreen> createState() => _CoverflowDemoScreenState();
}

class _CoverflowDemoScreenState extends State<CoverflowDemoScreen> {
  final CoverflowCarouselController _controller = CoverflowCarouselController();

  // Carousel Configurations
  bool _isInfinite = true;
  double _obscure = 0.4;
  double _viewportFraction = 0.28;
  CoverflowEntryAnimation _entryAnimation = CoverflowEntryAnimation.stack;
  int _activePage = 0;

  // Re-keying widget to easily trigger entry animation reload
  Key _carouselKey = UniqueKey();

  // Demo card colors & content
  final List<Map<String, dynamic>> _demoCards = [
    {
      'title': 'Nebula Voyage',
      'subtitle': 'Explore cosmic horizons',
      'colors': [Colors.deepPurple, Colors.pink],
      'icon': Icons.rocket_launch,
    },
    {
      'title': 'Oceanic Abyss',
      'subtitle': 'Deep sea discoveries',
      'colors': [Colors.blue, Colors.cyan],
      'icon': Icons.sailing,
    },
    {
      'title': 'Sunset Dunes',
      'subtitle': 'Warm desert winds',
      'colors': [Colors.orange, Colors.red],
      'icon': Icons.wb_sunny,
    },
    {
      'title': 'Forest Oasis',
      'subtitle': 'Ancient whispering woods',
      'colors': [Colors.teal, Colors.green],
      'icon': Icons.forest,
    },
    {
      'title': 'Aurora Sky',
      'subtitle': 'Northern lights dance',
      'colors': [Colors.purple, Colors.indigo],
      'icon': Icons.ac_unit,
    },
  ];

  void _reloadCarousel() {
    setState(() {
      _carouselKey = UniqueKey();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Coverflow Carousel Demo'),
        centerTitle: true,
        backgroundColor: Colors.transparent,
        elevation: 0,
      ),
      body: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 20),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              // 1. The Coverflow Carousel Container
              SizedBox(
                height: 380,
                child: Center(
                  child: CoverflowCarousel.builder(
                    key: _carouselKey,
                    controller: _controller,
                    itemCount: _demoCards.length,
                    itemWidth: 260,
                    itemHeight: 280,
                    visibleItems: 3,
                    isInfinite: _isInfinite,
                    obscure: _obscure,
                    viewportFraction: _viewportFraction,
                    entryAnimation: _entryAnimation,
                    entryAnimationDuration: const Duration(milliseconds: 1000),
                    entryAnimationCurve: Curves.easeOutBack,
                    onPageChanged: (index) {
                      setState(() {
                        _activePage = index;
                      });
                    },
                    itemBuilder: (context, index) {
                      final card = _demoCards[index];
                      return Container(
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(24),
                          gradient: LinearGradient(
                            colors: card['colors'] as List<Color>,
                            begin: Alignment.topLeft,
                            end: Alignment.bottomRight,
                          ),
                          boxShadow: [
                            BoxShadow(
                              color: (card['colors'] as List<Color>)
                                  .first
                                  .withOpacity(0.4),
                              blurRadius: 15,
                              offset: const Offset(0, 8),
                            ),
                          ],
                        ),
                        child: ClipRRect(
                          borderRadius: BorderRadius.circular(24),
                          child: Stack(
                            children: [
                              // Glassmorphic top glow overlay
                              Positioned(
                                top: -50,
                                left: -50,
                                child: Container(
                                  width: 150,
                                  height: 150,
                                  decoration: BoxDecoration(
                                    shape: BoxShape.circle,
                                    color: Colors.white.withOpacity(0.15),
                                  ),
                                ),
                              ),
                              Padding(
                                padding: const EdgeInsets.all(24.0),
                                child: Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  mainAxisAlignment: MainAxisAlignment.end,
                                  children: [
                                    Icon(
                                      card['icon'] as IconData,
                                      size: 48,
                                      color: Colors.white,
                                    ),
                                    const SizedBox(height: 24),
                                    Text(
                                      card['title'] as String,
                                      style: const TextStyle(
                                        color: Colors.white,
                                        fontSize: 22,
                                        fontWeight: FontWeight.bold,
                                      ),
                                    ),
                                    const SizedBox(height: 6),
                                    Text(
                                      card['subtitle'] as String,
                                      style: TextStyle(
                                        color: Colors.white.withOpacity(0.8),
                                        fontSize: 14,
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                            ],
                          ),
                        ),
                      );
                    },
                  ),
                ),
              ),

              // Active Page Indicator
              Text(
                'Focused Index: $_activePage',
                style: const TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.bold,
                  color: Colors.pinkAccent,
                ),
              ),
              const SizedBox(height: 16),

              // 2. Programmatic Controls
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  ElevatedButton.icon(
                    style: ElevatedButton.styleFrom(
                      backgroundColor: Colors.grey[850],
                      foregroundColor: Colors.white,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(12),
                      ),
                      padding: const EdgeInsets.symmetric(
                        horizontal: 16,
                        vertical: 12,
                      ),
                    ),
                    onPressed: () => _controller.previous(),
                    icon: const Icon(Icons.arrow_back),
                    label: const Text('Prev'),
                  ),
                  const SizedBox(width: 20),
                  ElevatedButton.icon(
                    style: ElevatedButton.styleFrom(
                      backgroundColor: Colors.grey[850],
                      foregroundColor: Colors.white,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(12),
                      ),
                      padding: const EdgeInsets.symmetric(
                        horizontal: 16,
                        vertical: 12,
                      ),
                    ),
                    onPressed: () => _controller.next(),
                    icon: const Icon(Icons.arrow_forward),
                    label: const Text('Next'),
                  ),
                ],
              ),
              const SizedBox(height: 30),

              // 3. Configurations Card Panel
              Container(
                margin: const EdgeInsets.symmetric(horizontal: 20),
                padding: const EdgeInsets.all(20),
                decoration: BoxDecoration(
                  color: const Color(0xFF161522),
                  borderRadius: BorderRadius.circular(20),
                  border: Border.all(color: Colors.white.withOpacity(0.05)),
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text(
                      'Interactive Configurations',
                      style: TextStyle(
                        fontSize: 18,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    const Divider(height: 24, color: Colors.grey),

                    // Infinite Scroll Toggle
                    SwitchListTile(
                      title: const Text('Infinite Scroll'),
                      subtitle: const Text('Enable wrap-around page looping'),
                      value: _isInfinite,
                      activeColor: Colors.deepPurpleAccent,
                      onChanged: (val) {
                        setState(() {
                          _isInfinite = val;
                        });
                      },
                    ),

                    // Obscure Blur Slider
                    ListTile(
                      title: const Text('Obscure Blur Intensity'),
                      subtitle: Slider(
                        value: _obscure,
                        min: 0.0,
                        max: 1.0,
                        divisions: 10,
                        activeColor: Colors.deepPurpleAccent,
                        label: _obscure.toStringAsFixed(1),
                        onChanged: (val) {
                          setState(() {
                            _obscure = val;
                          });
                        },
                      ),
                    ),

                    // Viewport Fraction Slider
                    ListTile(
                      title: const Text('Viewport Fraction (Drag Area)'),
                      subtitle: Slider(
                        value: _viewportFraction,
                        min: 0.15,
                        max: 0.45,
                        activeColor: Colors.deepPurpleAccent,
                        label: _viewportFraction.toStringAsFixed(2),
                        onChanged: (val) {
                          setState(() {
                            _viewportFraction = val;
                          });
                        },
                      ),
                    ),

                    // Entry Animation Selection Dropdown
                    ListTile(
                      title: const Text('Entry Animation'),
                      trailing: DropdownButton<CoverflowEntryAnimation>(
                        value: _entryAnimation,
                        underline: const SizedBox(),
                        onChanged: (CoverflowEntryAnimation? newValue) {
                          if (newValue != null) {
                            setState(() {
                              _entryAnimation = newValue;
                            });
                            _reloadCarousel();
                          }
                        },
                        items: CoverflowEntryAnimation.values.map((anim) {
                          return DropdownMenuItem<CoverflowEntryAnimation>(
                            value: anim,
                            child: Text(anim.name),
                          );
                        }).toList(),
                      ),
                    ),

                    const SizedBox(height: 12),
                    Center(
                      child: TextButton.icon(
                        style: TextButton.styleFrom(
                          foregroundColor: Colors.pinkAccent,
                        ),
                        onPressed: _reloadCarousel,
                        icon: const Icon(Icons.refresh),
                        label: const Text('Re-trigger Entry Animation'),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
12
likes
0
points
392
downloads

Publisher

verified publishermuditjpalvadi.tech

Weekly Downloads

A highly customizable 3D coverflow-style carousel for Flutter with smooth animations, perspective effects, and controller support.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on coverflow_carousel