flutter_magnetic_scroll 0.1.0 copy "flutter_magnetic_scroll: ^0.1.0" to clipboard
flutter_magnetic_scroll: ^0.1.0 copied to clipboard

A Flutter custom ScrollPhysics package for TikTok/Reels style feeds and pickers. Features magnetic snapping to fixed or variable item boundaries with physics-based smoothness.

example/lib/main.dart

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Magnetic Scroll Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MagneticScrollExample(),
    );
  }
}

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

  @override
  State<MagneticScrollExample> createState() => _MagneticScrollExampleState();
}

class _MagneticScrollExampleState extends State<MagneticScrollExample> {
  late MagneticScrollController _controller;
  int _currentIndex = 0;

  // We'll showcase variable sizes. Let's create a list of varying sizes.
  late List<double> _itemSizes;

  @override
  void initState() {
    super.initState();
    // Initialize dummy sizes: some 200, some 300, some 400
    _itemSizes = List.generate(20, (index) {
      if (index % 3 == 0) return 200.0;
      if (index % 3 == 1) return 300.0;
      return 400.0;
    });

    _controller = MagneticScrollController(itemSizes: _itemSizes);

    // Listen to changes for UI updates (e.g. playing the video in focus)
    _controller.currentIndex.addListener(() {
      setState(() {
        _currentIndex = _controller.currentIndex.value;
      });
      debugPrint('Item snapped into focus: $_currentIndex');
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Magnetic Scroll Features'),
        actions: [
          IconButton(
            icon: const Icon(Icons.arrow_downward),
            onPressed: () {
              // Programmatic navigation demonstration
              if (_currentIndex < _itemSizes.length - 1) {
                _controller.animateToItem(
                  index: _currentIndex + 1,
                  duration: const Duration(milliseconds: 400),
                );
              }
            },
          ),
          IconButton(
            icon: const Icon(Icons.arrow_upward),
            onPressed: () {
              if (_currentIndex > 0) {
                _controller.animateToItem(
                  index: _currentIndex - 1,
                  duration: const Duration(milliseconds: 400),
                );
              }
            },
          ),
        ],
      ),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text(
              'Current Focused Index: $_currentIndex',
              style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
          ),
          Expanded(
            child: ListView.builder(
              controller: _controller,
              // Use our custom scroll physics here!
              physics: MagneticScrollPhysics(
                itemSizes: _itemSizes,
                strictSingleItemSnapping: true, // Only snap one item per swipe
                onItemFocused: (index) {
                  // This is another way to listen to focus events directly from physics!
                  // It fires immediately when the physics starts the snap animation.
                  debugPrint('Physics targeted index: $index');
                },
              ),
              itemCount: _itemSizes.length,
              itemBuilder: (context, index) {
                // The actual scroll extent for this item is exactly `height`
                final height = _itemSizes[index];
                final isFocused = _currentIndex == index;
                final verticalMargin = 8.0;

                return AnimatedContainer(
                  duration: const Duration(milliseconds: 300),
                  // We subtract the vertical margins from the container height
                  // so that the total scroll extent exactly matches `height`
                  height: height - (verticalMargin * 2),
                  margin: EdgeInsets.symmetric(
                    vertical: verticalMargin,
                    horizontal: 16,
                  ),
                  decoration: BoxDecoration(
                    color: Colors.primaries[index % Colors.primaries.length],
                    borderRadius: BorderRadius.circular(16),
                    border: Border.all(
                      color: isFocused ? Colors.white : Colors.transparent,
                      width: 4,
                    ),
                    boxShadow: isFocused
                        ? [
                            const BoxShadow(
                              color: Colors.black26,
                              blurRadius: 10,
                            ),
                          ]
                        : [],
                  ),
                  child: Center(
                    child: Text(
                      'Item $index \nTotal Extent: $height',
                      textAlign: TextAlign.center,
                      style: const TextStyle(
                        fontSize: 28,
                        fontWeight: FontWeight.bold,
                        color: Colors.white,
                      ),
                    ),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}
0
likes
0
points
158
downloads

Publisher

verified publisherpinz.dev

Weekly Downloads

A Flutter custom ScrollPhysics package for TikTok/Reels style feeds and pickers. Features magnetic snapping to fixed or variable item boundaries with physics-based smoothness.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on flutter_magnetic_scroll