Giter Site home page Giter Site logo

flutter_cool_card_swiper's Introduction

Flutter Cool Card Swiper

Inspired by the original Swift UI implementation by @philipcdavis

🛠 Live preview & tincker with the code in this DartPad 🛠

This is how it looks

cool-swiper-web.mp4

Details

There are a few elements in this animation

  1. Cards stacked behind each other, the card’s scale & y position depend on their order (index) in the stack.
  2. When the user touches/clicks on the front card and holds, the card rotates a small angle, the center of that angle is relative to the pointer location (top-left/top-right/bottom-left/bottom-right), and the direction of the angle is based on the pointer location side (left => angle is positive, right => angle is negative)
  3. When the user starts dragging, the card moves with the poitner on the y-axis
  4. When the user releases, if the card travelled an initAnimationOffset distance, the main animation is triggerred, which is:
    1. Slide up a throwSlideYDistance & start full rotation (the rotation direction also depends on the pointer location like the animation in step 2)
    2. While rotating, slide down into the position of the furthest card in the stack
    3. Throughout the animation, scale down to scale of the furthest card in the stack
    4. The background cards scale up and slide down to replace the positioning of the animating card
  5. ⚠️ THE MAIN CATCH ⚠️ A short duration after the animation starts, a callback allows the parent stack to switch the location of the background cards (the cards that aren't animating) from being behind the animating card in the z-axis, to being in-front of it. This happens when the card is "in the air" so that when it lands back in the stack, it lands behind the other cards.

To achieve the above, the following widgets were used:

  1. Main Stack widget containing the cards
  2. GestureDetector widget that handles user drag input and starts animations accordingly with the methods:
    1. onVerticalDragStart (step 2 & 3 above)
    2. onVerticalDragUpdate (step 3 above)
    3. onVerticalDragEnd (step 4 & 5 above)
  3. A combination of animation widgets like TweenAnimationBuilder, AnimatedBuilder, AnimatedRotation, Transform.translate, Transform.rotate, Transform.scale to achieve the animations.
  4. IgnorePointer to allow touching/clicking on the forefront card only.
  5. A ValueListenableBuilder & ValueNotifier combination to rebuild only parts of the parent Stack widget without causing a rebuild of the widget being animated and thus resetting that animation half-way and not allowing it to complete. You can see this in this code snippet (the build method of the main CoolSwiper widget
@override
Widget build(BuildContext context) {
  return Stack(
    children: [
      ValueListenableBuilder(
        valueListenable: _backgroundCardsAreInFrontNotifier,
        builder: (c, bool backgroundCardsAreInFront, _) =>
            backgroundCardsAreInFront
                ? Positioned(child: Container())
                : _buildBackgroundCardsStack(),
      ),
      // The goal is not to rebuild this widget when the widgets around it ar swapped
      _buildFrontCard(),
      ValueListenableBuilder(
        valueListenable: _backgroundCardsAreInFrontNotifier,
        builder: (c, bool backgroundCardsAreInFront, _) =>
            backgroundCardsAreInFront
                ? _buildBackgroundCardsStack()
                : Positioned(child: Container()),
      ),
    ],
  );
}

Then these notifiers are updated in this function, which is called inside the onVerticalDragEnd in the card widget:

void _onAnimationTrigger() async {
  setState(() {
    fireBackgroundCardsAnimation = true;
  });
  backgroundCardsAnimationController.forward();
  Future.delayed(Constants.backgroundCardsAnimationDuration).then(
    (_) {
      _backgroundCardsAreInFrontNotifier.value = true;
    },
  );
  Future.delayed(Constants.swipeAnimationDuration).then(
    (_) {
      _backgroundCardsAreInFrontNotifier.value = false;
      backgroundCardsAnimationController.reset();
      _swapLast();
    },
  );
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.