The problem is I cant slide a image one by one and display three images. Image above is what I am trying to achieve.
Display three image in a slider and then slide one by one to the next one while still showing three images
The image above shoes my progress ,the lookof it is good but when I slide it , it slides threee images at a time , below is my code.
Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 50,
height: 400,
child: MaterialButton(
onPressed: () =>
buttonCarouselController.previousPage(
duration: const Duration(milliseconds: 300),
curve: Curves.linear),
child: const Icon(
size: 45.0,
Icons.arrow_back_ios,
color: Color.fromARGB(255, 98, 124, 133)),
),
),
Container(
width: widthDevice - 120,
height: 400,
child: CarouselSlider.builder(
itemCount: imageCount,
options: CarouselOptions(
autoPlay: true,
// aspectRatio: 3.0,
viewportFraction: 1,
),
carouselController: buttonCarouselController,
itemBuilder: (context, index, realIdx) {
final int first = index * 2;
final int second =
index <= (imageList.length / 2).ceil() - 1
? first + 1
: 0;
final int third =
index <= (imageList.length / 3).ceil() - 1
? first + 2
: 0;
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
children: [
Container(
width: widthDevice / 5,
height: widthDevice / 5,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
imageList[first]
['image']),
fit: BoxFit.cover)),
),
Container(
width: widthDevice / 5,
child: Padding(
padding:
const EdgeInsets.all(8.0),
child: Text(
imageList[first]
['description'],
style: GoogleFonts.montserrat(
textStyle: TextStyle(
fontSize: 14,
color: Color.fromARGB(
255, 51, 51, 51),
),
)),
),
),
],
),
SizedBox(
width: 35,
),
Column(
children: [
Container(
width: widthDevice / 5,
height: widthDevice / 5,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
imageList[second]
['image']),
fit: BoxFit.cover)),
),
Container(
width: widthDevice / 5,
child: Padding(
padding:
const EdgeInsets.all(8.0),
child: Text(
imageList[second]
['description'],
style: GoogleFonts.montserrat(
textStyle: TextStyle(
fontSize: 14,
color: Color.fromARGB(
255, 51, 51, 51),
),
)),
),
),
],
),
SizedBox(
width: 35,
),
Column(
children: [
Container(
width: widthDevice / 5,
height: widthDevice / 5,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
imageList[third]
['image']),
fit: BoxFit.cover)),
),
Container(
width: widthDevice / 5,
child: Padding(
padding:
const EdgeInsets.all(8.0),
child: Text(
imageList[third]
['description'],
style: GoogleFonts.montserrat(
textStyle: TextStyle(
fontSize: 14,
color: Color.fromARGB(
255, 51, 51, 51),
),
)),
),
),
],
),
],
),
],
);
},
)),
Container(
width: 50,
height: 400,
child: MaterialButton(
onPressed: () => buttonCarouselController.nextPage(
duration: const Duration(milliseconds: 300),
curve: Curves.linear),
child: const Icon(
size: 45.0,
Icons.arrow_forward_ios,
color: Color.fromARGB(255, 98, 124, 133)),
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: imageList.asMap().entries.map((entry) {
return GestureDetector(
onTap: () => _controller.animateToPage(entry.key),
child: Container(
width: 55.0,
height: 8.0,
margin: EdgeInsets.symmetric(
vertical: 8.0, horizontal: 4.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: (Theme.of(context).brightness ==
Brightness.dark
? Color.fromARGB(255, 98, 124, 133)
: const Color.fromARGB(
255, 252, 200, 178))
.withOpacity(
_current == entry.key ? 0.9 : 0.4)),
),
);
}).toList(),
),
],
))
Using a listview works
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';
import 'package:sattin/model/cart_model.dart';
import 'package:image_network/image_network.dart';
const _horizontalPadding = 32.0;
const _horizontalDesktopPadding = 40.0;
const _carouselHeightMin = 240.0;
const _carouselItemDesktopMargin = 8.0;
const _carouselItemMobileMargin = 4.0;
const _carouselItemWidth = 500.0;
class _DesktopPageButton extends StatelessWidget {
const _DesktopPageButton({
this.isEnd = false,
this.onTap,
});
final bool isEnd;
final GestureTapCallback? onTap;
@override
Widget build(BuildContext context) {
const buttonSize = 58.0;
const padding = _horizontalDesktopPadding - buttonSize / 2;
return ExcludeSemantics(
child: Align(
alignment: isEnd
? AlignmentDirectional.centerEnd
: AlignmentDirectional.centerStart,
child: Container(
width: buttonSize,
height: buttonSize,
margin: EdgeInsetsDirectional.only(
start: isEnd ? 0 : padding,
end: isEnd ? padding : 0,
),
child: MaterialButton(
onPressed: onTap,
child: Icon(
size: 45.0,
isEnd ? Icons.arrow_forward_ios : Icons.arrow_back_ios,
color: Color.fromARGB(255, 98, 124, 133)),
),
),
),
);
}
}
class _DesktopCarousel extends StatefulWidget {
Function(String)? updateCount;
_DesktopCarousel({super.key, required this.updateCount});
@override
_DesktopCarouselState createState() => _DesktopCarouselState();
}
class _DesktopCarouselState extends State<_DesktopCarousel> {
late ScrollController _controller;
@override
void initState() {
super.initState();
_controller = ScrollController();
_controller.addListener(() {
setState(() {});
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
var widthDevice = MediaQuery.of(context).size.width;
var showPreviousButton = false;
var showNextButton = true;
// Only check this after the _controller has been attached to the ListView.
if (_controller.hasClients) {
showPreviousButton = _controller.offset > 0;
showNextButton =
_controller.offset < _controller.position.maxScrollExtent;
}
return Align(
alignment: Alignment.center,
child: Consumer<CartModel>(builder: (context, value, child) {
return Container(
height: 450,
constraints: const BoxConstraints(maxWidth: 1500),
child: Stack(
children: [
ListView.builder(
padding: EdgeInsets.symmetric(
horizontal:
_horizontalDesktopPadding - _carouselItemDesktopMargin,
),
scrollDirection: Axis.horizontal,
primary: false,
controller: _controller,
itemExtent: widthDevice / 4,
itemCount: value.specialItems.length,
itemBuilder: (context, index) => Padding(
padding: const EdgeInsets.symmetric(vertical: 0.0),
child: Padding(
padding: const EdgeInsets.all(25.0),
child: _CarouselCard(
image: value.specialItems[index]['image'],
cost: value.specialItems[index]["cost"],
description: value.specialItems[index]["description"]),
),
),
),
if (showPreviousButton)
_DesktopPageButton(
onTap: () {
widget.updateCount!("-");
_controller.animateTo(
_controller.offset - _carouselItemWidth,
duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut,
);
},
),
if (showNextButton)
_DesktopPageButton(
isEnd: true,
onTap: () {
widget.updateCount!("+");
_controller.animateTo(
_controller.offset + _carouselItemWidth,
duration: const Duration(milliseconds: 200),
curve: Curves.easeInOut,
);
},
),
],
),
);
}),
);
}
}
class _CarouselCard extends StatelessWidget {
String? description;
String? image;
String? cost;
_CarouselCard(
{super.key,
required this.description,
required this.image,
required this.cost});
@override
Widget build(BuildContext context) {
var widthDevice = MediaQuery.of(context).size.width;
return Column(
children: [
ImageNetwork(
image: image!,
width: 500,
height: 350,
),
Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(description! + " - NOW " + "R" + cost!,
style: GoogleFonts.montserrat(
textStyle: TextStyle(
fontSize: 14,
color: Color.fromARGB(255, 51, 51, 51),
),
)),
),
),
],
);
}
}
class SpecialsDisplay2 extends StatefulWidget {
const SpecialsDisplay2({super.key});
@override
State<SpecialsDisplay2> createState() => _SpecialsDisplay2State();
}
class _SpecialsDisplay2State extends State<SpecialsDisplay2> {
@override
Widget build(BuildContext context) {
return Consumer<CartModel>(builder: (context, value, child) {
int _counter = 0;
updateCount(String forwardBack) {
setState(() {
_counter = _counter + 1;
});
print(_counter);
}
return Container(
color: Colors.white,
child: Column(
children: [
SizedBox(
height: 60,
),
Text('RADIANT SALE',
style: GoogleFonts.montserrat(
textStyle: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w600,
color: Color.fromARGB(255, 51, 51, 51),
),
)),
SizedBox(
height: 25,
),
_DesktopCarousel(updateCount: updateCount),
/* Row(
mainAxisAlignment: MainAxisAlignment.center,
children: imageList.asMap().entries.map((entry) {
return GestureDetector(
// onTap: () => _controller.animateToPage(entry.key),
child: Container(
width: 35.0,
height: 8.0,
margin:
EdgeInsets.symmetric(vertical: 8.0, horizontal: 4.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: (Theme.of(context).brightness == Brightness.dark
? Color.fromARGB(255, 98, 124, 133)
: const Color.fromARGB(255, 252, 200, 178))
.withOpacity(_counter == entry.key ? 0.9 : 0.4)),
),
);
}).toList(),
)*/
],
),
);
});
}
}