snap 2.0.0 copy "snap: ^2.0.0" to clipboard
snap: ^2.0.0 copied to clipboard

An extensive snap tool/widget for Flutter that allows very flexible snap management and snapping between your widgets.

example/lib/main.dart

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// © Cosmos Software | Ali Yigit Bireroglu                                                                                                           /
// All material used in the making of this code, project, program, application, software et cetera (the "Intellectual Property")                     /
// belongs completely and solely to Ali Yigit Bireroglu. This includes but is not limited to the source code, the multimedia and                     /
// other asset files. If you were granted this Intellectual Property for personal use, you are obligated to include this copyright                   /
// text at all times.                                                                                                                                /
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//@formatter:off

import 'package:flutter/material.dart';

import 'package:snap/snap.dart';

List<GlobalKey> bounds = [];
List<GlobalKey> views = [];

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Snap Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: MyHomePage(title: 'Snap Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, this.title}) : super(key: key);

  final String? title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  double bottom = -200.0;

  @override
  void initState() {
    super.initState();

    for (int i = 0; i < 6; i++) {
      bounds.add(GlobalKey());
      views.add(GlobalKey());
    }
  }

  Widget description(String text) {
    return Container(
      constraints: const BoxConstraints.expand(height: 75),
      color: Colors.green,
      child: Center(
        child: Padding(
          padding: const EdgeInsets.all(10),
          child: Text(
            text,
            style: const TextStyle(
              color: Colors.white,
              fontWeight: FontWeight.bold,
              fontSize: 15,
            ),
            textAlign: TextAlign.center,
          ),
        ),
      ),
    );
  }

  Widget gap() {
    return Container(
      constraints: const BoxConstraints.expand(height: 25),
      color: Colors.transparent,
      child: Center(
        child: const Text(
          "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ",
          style: const TextStyle(
            color: Colors.black,
            fontWeight: FontWeight.bold,
            fontSize: 10,
          ),
          textAlign: TextAlign.center,
        ),
      ),
    );
  }

  Widget normalBox(Key key, String text, Color color) {
    return Container(
      key: key,
      width: 200,
      height: 200,
      color: Colors.transparent,
      child: Padding(
        padding: const EdgeInsets.all(5),
        child: Container(
          constraints: BoxConstraints.expand(),
          decoration: BoxDecoration(
            color: color,
            borderRadius: const BorderRadius.all(const Radius.circular(10.0)),
          ),
          child: Center(
            child: Text(
              text,
              style: const TextStyle(
                color: Colors.white,
                fontWeight: FontWeight.bold,
                fontSize: 25,
              ),
              textAlign: TextAlign.center,
            ),
          ),
        ),
      ),
    );
  }

  Widget translatedBox(Key key, String text, Color color) {
    return Transform.translate(
      offset: const Offset(50, 50),
      child: Container(
        key: key,
        width: 200,
        height: 200,
        color: Colors.transparent,
        child: Padding(
          padding: const EdgeInsets.all(5),
          child: Container(
            constraints: BoxConstraints.expand(),
            decoration: BoxDecoration(
              color: color,
              borderRadius: const BorderRadius.all(const Radius.circular(10.0)),
            ),
            child: Center(
              child: Text(
                text,
                style: const TextStyle(
                  color: Colors.white,
                  fontWeight: FontWeight.bold,
                  fontSize: 25,
                ),
                textAlign: TextAlign.center,
              ),
            ),
          ),
        ),
      ),
    );
  }

  Widget smallBox(Key key, String text, Color color) {
    return Container(
      key: key,
      width: 50,
      height: 50,
      color: Colors.transparent,
      child: Padding(
        padding: const EdgeInsets.all(5),
        child: Container(
          constraints: BoxConstraints.expand(),
          decoration: BoxDecoration(
            color: color,
            borderRadius: const BorderRadius.all(const Radius.circular(0.0)),
          ),
          child: Center(
            child: Text(
              text,
              style: const TextStyle(
                color: Colors.white,
                fontWeight: FontWeight.bold,
                fontSize: 25,
              ),
              textAlign: TextAlign.center,
            ),
          ),
        ),
      ),
    );
  }

  Widget dottedBox(Key key, String text, Color color) {
    return Transform.translate(
      offset: const Offset(75, 100),
      child: Container(
        key: key,
        width: 200,
        height: 200,
        color: Colors.transparent,
        child: Stack(
          children: [
            Padding(
              padding: const EdgeInsets.all(5),
              child: Container(
                constraints: BoxConstraints.expand(),
                decoration: BoxDecoration(
                  color: color,
                  borderRadius: const BorderRadius.all(const Radius.circular(10.0)),
                ),
                child: Center(
                  child: Text(
                    text,
                    style: const TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.bold,
                      fontSize: 25,
                    ),
                    textAlign: TextAlign.center,
                  ),
                ),
              ),
            ),
            Align(
              alignment: const Alignment(-0.9, -0.9),
              child: Container(
                width: 10,
                height: 10,
                color: Colors.orangeAccent,
              ),
            ),
            Align(
              alignment: const Alignment(0.9, -0.9),
              child: Container(
                width: 10,
                height: 10,
                color: Colors.black,
              ),
            ),
            Align(
              alignment: const Alignment(-0.9, 0.9),
              child: Container(
                width: 10,
                height: 10,
                color: Colors.deepPurpleAccent,
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget firstNormalBoxView() {
    return normalBox(
      views[0],
      "Move & Snap",
      Colors.redAccent,
    );
  }

  Widget animatedBoxView() {
    return normalBox(
      views[1],
      "Move & Snap",
      Colors.redAccent,
    );
  }

  Widget dottedBoxView() {
    return dottedBox(
      views[2],
      "Move & Snap",
      Colors.redAccent,
    );
  }

  Widget translatedBoxView() {
    return translatedBox(
      views[3],
      "Move & Snap",
      Colors.redAccent,
    );
  }

  Widget smallBoxView() {
    return smallBox(
      views[4],
      "*",
      Colors.redAccent,
    );
  }

  Widget secondNormalBoxView() {
    return normalBox(
      views[5],
      "Move & Snap",
      Colors.redAccent,
    );
  }

  Widget thirdNormalBoxView() {
    return normalBox(
      views[6],
      "Move & Snap",
      Colors.redAccent,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title!)),
      body: PageView(
        onPageChanged: (int index) {
          if (index == 1)
            setState(() {
              bottom = 0.0;
            });
          else
            setState(() {
              bottom = -200.0;
            });
        },
        children: [
          Scaffold(
            body: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                description("The box will snap to the corners or the center."),
                gap(),
                Expanded(
                  child: Align(
                    key: bounds[0],
                    alignment: const Alignment(-1.0, -1.0),
                    child: SnapController(
                      firstNormalBoxView(),
                      true,
                      views[0],
                      bounds[0],
                      Offset.zero,
                      const Offset(1.0, 1.0),
                      const Offset(0.75, 0.75),
                      const Offset(0.75, 0.75),
                      snapTargets: [
                        const SnapTarget(Pivot.topLeft, Pivot.topLeft),
                        const SnapTarget(Pivot.topRight, Pivot.topRight),
                        const SnapTarget(Pivot.bottomLeft, Pivot.bottomLeft),
                        const SnapTarget(Pivot.bottomRight, Pivot.bottomRight),
                        const SnapTarget(Pivot.center, Pivot.center),
                      ],
                      minSnapDistance: 100,
                    ),
                  ),
                ),
              ],
            ),
          ),
          Scaffold(
            body: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                description("The box will snap to the closest side regardless of animation."),
                gap(),
                Expanded(
                  child: Align(
                    key: bounds[1],
                    alignment: const Alignment(-1.0, -1.0),
                    child: Stack(
                      children: [
                        AnimatedPositioned(
                          left: 0,
                          bottom: bottom,
                          duration: Duration(milliseconds: 300),
                          child: SnapController(
                            animatedBoxView(),
                            true,
                            views[1],
                            bounds[1],
                            Offset.zero,
                            const Offset(1.0, 1.0),
                            const Offset(0.75, 0.75),
                            const Offset(0.75, 0.75),
                            snapTargets: [
                              const SnapTarget(Pivot.closestAny, Pivot.closestAny),
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
          Scaffold(
            body: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                description("The box will snap to the closest matching color."),
                gap(),
                Expanded(
                  child: Stack(
                    children: [
                      Align(
                        key: bounds[2],
                        alignment: const Alignment(-1.0, -1.0),
                        child: SnapController(
                          dottedBoxView(),
                          true,
                          views[2],
                          bounds[2],
                          Offset.zero,
                          const Offset(1.0, 1.0),
                          const Offset(0.75, 0.75),
                          const Offset(0.75, 0.75),
                          snapTargets: [
                            const SnapTarget(const Offset(0.1, 0.1), const Offset(0.1, 0.1)),
                            const SnapTarget(const Offset(0.9, 0.1), const Offset(0.85, 0.465)),
                            const SnapTarget(const Offset(0.1, 0.9), const Offset(0.1, 0.9)),
                          ],
                        ),
                      ),
                      Align(
                        alignment: const Alignment(-0.85, -0.85),
                        child: Container(
                          width: 10,
                          height: 10,
                          color: Colors.orangeAccent,
                        ),
                      ),
                      Align(
                        alignment: const Alignment(0.75, -0.1),
                        child: Container(
                          width: 10,
                          height: 10,
                          color: Colors.black,
                        ),
                      ),
                      Align(
                        alignment: const Alignment(-0.85, 0.85),
                        child: Container(
                          width: 10,
                          height: 10,
                          color: Colors.deepPurpleAccent,
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
          Scaffold(
            body: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                description("The box will snap to the corners or the center while maintaining the initial offset"),
                gap(),
                Expanded(
                  child: Align(
                    key: bounds[3],
                    alignment: const Alignment(-1.0, -1.0),
                    child: SnapController(
                      translatedBoxView(),
                      true,
                      views[3],
                      bounds[3],
                      Offset(50.0 / MediaQuery.of(context).size.width, 50.0 / MediaQuery.of(context).size.height),
                      Offset(1.0, 1.0) - Offset(50.0 / MediaQuery.of(context).size.width, 50.0 / MediaQuery.of(context).size.height),
                      const Offset(0.75, 0.75),
                      const Offset(0.75, 0.75),
                      snapTargets: [
                        SnapTarget(Pivot.topLeft, Offset(50.0 / MediaQuery.of(context).size.width, 50.0 / MediaQuery.of(context).size.height)),
                        SnapTarget(Pivot.topRight, Offset(1.0 - 50.0 / MediaQuery.of(context).size.width, 50.0 / MediaQuery.of(context).size.height)),
                        SnapTarget(Pivot.bottomLeft, Offset(50.0 / MediaQuery.of(context).size.width, 1.0 - 50.0 / MediaQuery.of(context).size.height)),
                        SnapTarget(Pivot.bottomRight, Offset(1.0, 1.0) - Offset(50.0 / MediaQuery.of(context).size.width, 50.0 / MediaQuery.of(context).size.height)),
                        const SnapTarget(Pivot.center, Pivot.center),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
          Scaffold(
            body: Column(
              children: [
                description("The box will snap to the closest side or the center within its container."),
                gap(),
                Container(
                  width: 300,
                  height: 300,
                  color: Colors.orangeAccent,
                  child: Align(
                    key: bounds[4],
                    alignment: const Alignment(-1.0, -1.0),
                    child: SnapController(
                      smallBoxView(),
                      true,
                      views[4],
                      bounds[4],
                      Offset.zero,
                      const Offset(1.0, 1.0),
                      const Offset(0.15, 0.15),
                      const Offset(0.15, 0.15),
                      snapTargets: [
                        const SnapTarget(Pivot.closestAny, Pivot.closestAny),
                        const SnapTarget(Pivot.center, Pivot.center),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
          Scaffold(
            body: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                description("The box will snap to the corners or the center without animation."),
                gap(),
                Expanded(
                  child: Align(
                    key: bounds[5],
                    alignment: const Alignment(-1.0, -1.0),
                    child: SnapController(
                      secondNormalBoxView(),
                      false,
                      views[5],
                      bounds[5],
                      Offset.zero,
                      const Offset(1.0, 1.0),
                      const Offset(0.75, 0.75),
                      const Offset(0.75, 0.75),
                      snapTargets: [
                        const SnapTarget(Pivot.topLeft, Pivot.topLeft),
                        const SnapTarget(Pivot.topRight, Pivot.topRight),
                        const SnapTarget(Pivot.bottomLeft, Pivot.bottomLeft),
                        const SnapTarget(Pivot.bottomRight, Pivot.bottomRight),
                        const SnapTarget(Pivot.center, Pivot.center),
                      ],
                      animateSnap: false,
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}
21
likes
150
points
58
downloads

Publisher

verified publishercosmossoftware.coffee

Weekly Downloads

An extensive snap tool/widget for Flutter that allows very flexible snap management and snapping between your widgets.

Homepage
Repository (GitHub)

Documentation

API reference

License

MIT (license)

Dependencies

flick, flutter

More

Packages that depend on snap