Search code examples
flutterdartcarouselflutter-widget

Swiping through cards in a vertical carousel in Flutter


I'm trying to create a social media feed where each post is a card of a different size, one on top of the other (almost like a vertical carousel). For each card, the user can swipe right to like, left to dislike, and up to skip. When the user swipes left or right, the cards in the bottom have to come up to the center of the screen, occupying its place (think of it as a mix between Tinder and Tiktok).

Here's an animation showing exactly what I need

I'm still learning Flutter and have no idea what widgets to use to achieve this. Any ideas of how to make this work?


Solution

  • The Dismissible widget should be what you need

    void main() {
      runApp(Screen());
    }
    
    class Screen extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            body: Screen1(),
          ),
        );
      }
    }
    

    Edit :

    class Screen1 extends StatefulWidget {
      @override
      _Screen1State createState() => _Screen1State();
    }
    class _Screen1State extends State<Screen1> {
      final List<Color> colors = [Colors.red, Colors.blue, Colors.yellow, Colors.green];
    
      @override
      Widget build(BuildContext context) {
        return PageView.builder(
            controller: PageController(viewportFraction: 0.8),
            scrollDirection: Axis.vertical,
            itemCount: colors.length,
            itemBuilder: (context, index) {
              return Padding(
                padding: const EdgeInsets.all(20),
                child: AnimatedSwitcher(
                  transitionBuilder: (child, animation) {
                    return SlideTransition(
                        child: child,
                        position:
                            Tween<Offset>(begin: Offset(0, 1), end: Offset(0, 0)).animate(animation));
                  },
                  duration: Duration(milliseconds: 200),
                  child: Dismissible(
                    movementDuration: Duration(milliseconds: 1),
                    resizeDuration: Duration(milliseconds: 1),
                    onDismissed: (direction) {
                      setState(() {
                        colors.remove(colors[index]);
                      });
                    },
                    key: ValueKey(colors[index]),
                    child: Container(
                      width: (200+index*75).toDouble(),
                      color: colors[index],
                    ),
                  ),
                ),
              );
            });
      }
    }