I want to create a list of cards scrolling horizontally with snap to fit effect when swiped either from left or right.
Each card has some spacing between them and fit to screen similar to below image
Apart from that these horizontally scrollable list elements should be contained inside a vertically scrollable list.
I all I am able to achieve is only displaying a list of horizontal scrolling cards after following example in flutter docs.
class SnapCarousel extends StatelessWidget { @override Widget build(BuildContext context) { final title = 'Horizontal List'; return MaterialApp( title: title, home: Scaffold( appBar: AppBar( title: Text(title), ), body: Container( margin: EdgeInsets.symmetric(vertical: 20.0), height: 200.0, child: ListView( scrollDirection: Axis.horizontal, children: <Widget>[ Container( width: 160.0, color: Colors.red, ), Container( width: 160.0, color: Colors.blue, ), Container( width: 160.0, color: Colors.green, ), Container( width: 160.0, color: Colors.yellow, ), Container( width: 160.0, color: Colors.orange, ), ], ), ), ), ); } }
To scroll a Flutter ListView widget horizontally, set scrollDirection property of the ListView widget to Axis. horizontal. This arranges the items side by side horzontally. Following is the basic syntax to arrange the items horizontally in a ListView and scroll them horizontally.
You may want to change the scroll direction when the GridView is displayed in landscape mode. Setting scrollDirection to Axis. horizontal will do just that.
Use PageView
and ListView
:
import 'package:flutter/material.dart'; main() => runApp(MaterialApp(home: MyHomePage())); class MyHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Carousel in vertical scrollable'), ), body: ListView.builder( padding: EdgeInsets.symmetric(vertical: 16.0), itemBuilder: (BuildContext context, int index) { if(index % 2 == 0) { return _buildCarousel(context, index ~/ 2); } else { return Divider(); } }, ), ); } Widget _buildCarousel(BuildContext context, int carouselIndex) { return Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ Text('Carousel $carouselIndex'), SizedBox( // you may want to use an aspect ratio here for tablet support height: 200.0, child: PageView.builder( // store this controller in a State to save the carousel scroll position controller: PageController(viewportFraction: 0.8), itemBuilder: (BuildContext context, int itemIndex) { return _buildCarouselItem(context, carouselIndex, itemIndex); }, ), ) ], ); } Widget _buildCarouselItem(BuildContext context, int carouselIndex, int itemIndex) { return Padding( padding: EdgeInsets.symmetric(horizontal: 4.0), child: Container( decoration: BoxDecoration( color: Colors.grey, borderRadius: BorderRadius.all(Radius.circular(4.0)), ), ), ); } }
Screenshot:
If you don't want to use any 3rd party packages, you can simply try this:
class _HomePageState extends State<HomePage> { int _index = 0; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: Center( child: SizedBox( height: 200, // card height child: PageView.builder( itemCount: 10, controller: PageController(viewportFraction: 0.7), onPageChanged: (int index) => setState(() => _index = index), itemBuilder: (_, i) { return Transform.scale( scale: i == _index ? 1 : 0.9, child: Card( elevation: 6, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), child: Center( child: Text( "Card ${i + 1}", style: TextStyle(fontSize: 32), ), ), ), ); }, ), ), ), ); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With