Search code examples
flutterimagedartslidercarousel-slider

How to create a imageslider with three images and slide one by one image


enter image description here 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

enter image description here

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(),
                  ),
                ],
              ))
     

Solution

  • 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(),
                )*/
              ],
            ),
          );
        });
      }
    }