scroll_snap_widgets 0.0.7 copy "scroll_snap_widgets: ^0.0.7" to clipboard
scroll_snap_widgets: ^0.0.7 copied to clipboard

A Flutter package to implement snapping items view without PageView. Scrolling stops automatically on an item providing a unique scrolling experience through items.

example/lib/main.dart

import 'package:example/data.dart';
import 'package:scroll_snap_widgets/scroll_snap_widgets.dart';
import 'package:example/widgets.dart';
import 'package:flutter/material.dart';

/*
This is an example file for the Flutter package called scroll_snap_widget
this widget allows us to implement accurate auto-stopping on items in a horizontal or vertical scroll view
it gives a unique scrolling experience, it should not be used if you want to implement fast scrolling,
as it prevents more scrolling than the itemSize and brings the user back to the start of the item (the item can be any Widget)

Please find the assets and data.dart and widgets.dart files from the GitHub repository example to run this code perfectly
or clone the project and run the example, if you want to get the exact or similar output
Of course, you are welcome to try it yourself, this example is just a demonstration of its capabilities, you can use it in many ways

Hope it helps, let me know if there are any bugs or any new features ideas in the GitHub issue section.

Created by,
Aayush-Thacker
*/

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

///the first app widget to build the MaterialApp
class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Scroll Snap Widgets Example',
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      home: const HomePage(),
    );
  }
}

///HomePage of the example with 2 buttons and an appbar
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      ///appbar with constant title
      appBar: AppBar(
        title: const Text('Scroll Snap Widgets Example'),
        centerTitle: true,
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          ///first button takes to the HorizontalItems screen
          Expanded(
            child: Padding(
              padding: const EdgeInsets.all(8),
              child: Card(
                margin: EdgeInsets.zero,
                color: Colors.redAccent,
                child: InkWell(
                  onTap: () {
                    Navigator.push(
                        context,
                        MaterialPageRoute(
                            builder: (_) => const HorizontalItems()));
                  },
                  child: const Center(
                    child: Text(
                      'Horizontal Items',
                      style: TextStyle(fontSize: 30, color: Colors.white),
                    ),
                  ),
                ),
              ),
            ),
          ),

          ///second button takes to the VerticalItems screen
          Expanded(
            child: Padding(
              padding: const EdgeInsets.only(bottom: 8, right: 8, left: 8),
              child: Card(
                margin: EdgeInsets.zero,
                color: Colors.redAccent,
                child: InkWell(
                  onTap: () {
                    Navigator.push(
                        context,
                        MaterialPageRoute(
                            builder: (_) => const VerticalItems()));
                  },
                  child: const Center(
                    child: Text(
                      'Vertical Items',
                      style: TextStyle(fontSize: 30, color: Colors.white),
                    ),
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

///page to saw the use cases of package with horizontal scrollable items
class HorizontalItems extends StatefulWidget {
  const HorizontalItems({super.key});

  @override
  State<HorizontalItems> createState() => _HorizontalItemsState();
}

class _HorizontalItemsState extends State<HorizontalItems> {
  static const double bigItemWidth = 300;

  ///controller for animated example
  final ScrollSnapWidgetsController _controllerAnimate =
      ScrollSnapWidgetsController(size: bigItemWidth);

  ///controller for jumping example
  final ScrollSnapWidgetsController _controllerJump =
      ScrollSnapWidgetsController(size: bigItemWidth);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Horizontal Items'),
        centerTitle: true,
      ),
      body: SingleChildScrollView(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            const Padding(
              padding: EdgeInsets.all(8.0),
              child: Text(
                'Normall Snapping Scrollable Items',
                style: TextStyle(fontSize: 20),
              ),
            ),

            ///simple use case without controller
            ScrollSnapWidgets(
                padding: EdgeInsets.zero,

                ///widget size is height in this example
                widgetSize: 200,
                scrollDirection: Axis.horizontal,

                ///item size is item's width
                itemSize: 200,
                itemBuilder: (itemIndex) => SimpleItemCard(
                      ///keep same as item size
                      widgth: 200,
                      item: Data.allItems[itemIndex],
                    ),
                itemCount: Data.allItems.length),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Row(
                children: [
                  const Expanded(
                    child: Text(
                      'Animate Next Previous',
                      style: TextStyle(
                          fontSize: 20, overflow: TextOverflow.ellipsis),
                    ),
                  ),
                  IconButton(
                    onPressed: () {
                      ///animate previous with the default curve and duration
                      _controllerAnimate.animatePrevious();
                    },
                    icon: const Icon(Icons.navigate_before),
                  ),
                  IconButton(
                    onPressed: () {
                      ///animaet next with custom curve and duration
                      _controllerAnimate.animateNext(
                          duration: const Duration(seconds: 1),
                          curve: Curves.linearToEaseOut);
                    },
                    icon: const Icon(Icons.navigate_next),
                  ),
                ],
              ),
            ),

            ///example with controller to control the widget's scroll event programetically
            ScrollSnapWidgets(
                controller: _controllerAnimate,
                padding: EdgeInsets.zero,

                ///widget's width
                widgetSize: 300,
                scrollDirection: Axis.horizontal,
                itemSize: bigItemWidth,
                itemBuilder: (itemIndex) => SimpleItemCard(
                      widgth: bigItemWidth,
                      item: Data.allItems[itemIndex],
                    ),
                itemCount: Data.allItems.length),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Row(
                children: [
                  const Expanded(
                    child: Text(
                      'Jump Next Previous',
                      style: TextStyle(
                          fontSize: 20, overflow: TextOverflow.ellipsis),
                    ),
                  ),
                  IconButton(
                    onPressed: () {
                      ///controller function call for previous jumping
                      _controllerJump.jumpPrevious();
                    },
                    icon: const Icon(Icons.navigate_before),
                  ),
                  IconButton(
                    onPressed: () {
                      ///controller function call for next jumping
                      _controllerJump.jumpNext();
                    },
                    icon: const Icon(Icons.navigate_next),
                  ),
                ],
              ),
            ),
            ScrollSnapWidgets(
                controller: _controllerJump,
                padding: EdgeInsets.zero,

                ///width of the widget
                widgetSize: 300,
                scrollDirection: Axis.horizontal,
                itemSize: bigItemWidth,
                itemBuilder: (itemIndex) => SimpleItemCard(
                      widgth: bigItemWidth,
                      item: Data.allItems[itemIndex],
                    ),
                itemCount: Data.allItems.length),
          ],
        ),
      ),
    );
  }

  ///the dispose method of the controller disposes of the scroll controller
  @override
  void dispose() {
    _controllerAnimate.dispose();
    _controllerJump.dispose();
    super.dispose();
  }
}

///example to demonstrate Vertically snapping items that stop autometically when user scrolls like instagram posts
class VerticalItems extends StatefulWidget {
  const VerticalItems({super.key});

  @override
  State<VerticalItems> createState() => _VerticalItemsState();
}

class _VerticalItemsState extends State<VerticalItems> {
  static const double itemHeight = 500;

  ///controller for handling custom scroll event callbacks
  final ScrollSnapWidgetsController _controller =
      ScrollSnapWidgetsController(size: itemHeight);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Vertical Items'),
        centerTitle: true,
      ),
      body: SizedBox(
        height: double.maxFinite,
        width: double.maxFinite,
        child: Stack(
          ///defines the width of the widget
          fit: StackFit.expand,
          children: [
            ///vertical scrollable items with controller example
            ScrollSnapWidgets(
                controller: _controller,

                ///widget height
                widgetSize: double.maxFinite,
                scrollDirection: Axis.vertical,

                ///item height
                itemSize: itemHeight,
                itemBuilder: (itemIndex) => SimpleItemCard(
                      ///same height as above
                      height: itemHeight,
                      item: Data.allItems[itemIndex],
                    ),
                itemCount: Data.allItems.length),
            Align(
              alignment: Alignment.bottomRight,
              child: SizedBox(
                width: 100,
                height: 200,
                child: Card(
                  color: Colors.white.withOpacity(0.6),
                  elevation: 5,
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      Expanded(
                        child: InkWell(
                          onTap: () {
                            ///function call to animate to the starting point
                            _controller.animateStart();
                          },
                          child: Column(
                            mainAxisSize: MainAxisSize.min,
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: const [
                              Icon(
                                Icons.arrow_upward,
                                size: 35,
                              ),
                              Text('Animate Start'),
                            ],
                          ),
                        ),
                      ),
                      Expanded(
                        child: InkWell(
                          onTap: () {
                            ///function call to animate to the ending point with custom duration
                            _controller.animateEnd(
                                duration: const Duration(seconds: 2));
                          },
                          child: Column(
                            mainAxisSize: MainAxisSize.min,
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: const [
                              Text('Animate End'),
                              Icon(
                                Icons.arrow_downward,
                                size: 35,
                              ),
                            ],
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
            Align(
              alignment: Alignment.bottomLeft,
              child: SizedBox(
                width: 100,
                height: 200,
                child: Card(
                  color: Colors.white.withOpacity(0.6),
                  elevation: 5,
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      Expanded(
                        child: InkWell(
                          onTap: () {
                            ///function call for jumping to the starting point
                            _controller.jumpStart();
                          },
                          child: Column(
                            mainAxisSize: MainAxisSize.min,
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: const [
                              Icon(
                                Icons.arrow_upward,
                                size: 35,
                              ),
                              Text('Jump Start'),
                            ],
                          ),
                        ),
                      ),
                      Expanded(
                        child: InkWell(
                          onTap: () {
                            ///function call for jumping to the ending point
                            _controller.jumpEnd();
                          },
                          child: Column(
                            mainAxisSize: MainAxisSize.min,
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: const [
                              Text('Jump End'),
                              Icon(
                                Icons.arrow_downward,
                                size: 35,
                              ),
                            ],
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  ///the dispose method of the controller disposes of the scroll controller
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}
7
likes
150
points
453
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter package to implement snapping items view without PageView. Scrolling stops automatically on an item providing a unique scrolling experience through items.

Repository (GitHub)

Documentation

API reference

License

BSD-2-Clause (license)

Dependencies

flutter

More

Packages that depend on scroll_snap_widgets