Flutter ImageSlideshow click through

Issue

I want to click trough my ImageSlideshow in Flutter web.
is this possible and how, now i only can swipe through it.

This is the Code

ImageSlideshow(
                  width: 400,
                  height: 800,
                  initialPage: 0,
                  indicatorColor: HexColor("#ff9900"),
                  indicatorBackgroundColor: Colors.grey,
                  children: [
                    Image.asset(
                      'third.png',
                      fit: BoxFit.cover,
                    ),
                    Image.asset(
                      'second.png',
                      fit: BoxFit.cover,
                    ),
                    Image.asset(
                      'first.png',
                      fit: BoxFit.cover,
                    ),
                  ],
                  onPageChanged: (value) {
                    print('Page changed: $value');
                  },
                ),

This is the Stateless part where the error was born.

class Information extends StatelessWidget {

PageController _pageController;

  @override
  void initState() {
    _pageController = PageController(
  initialPage: 0,
    );
    super.initState();
  }

  @override
  void dispose() {
    _pageController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(

Thanks for any answer.

Solution

This feature isn’t built into that package but when you run into that scenario you can copy the package code and modify it. The main difference is that you have to create your own PageController and pass it into the ImageSlideShow. Then wrap each of the children in a GestureDetector and manually tell the _pageController to animate to the next page in the onTap.

Add this to your stateful widget where you have the ImageSlideShow.

 PageController _pageController;

  @override
  void initState() {
    _pageController = PageController(
      initialPage: 0,
    );
    super.initState();
  }

  @override
  void dispose() {
    _pageController.dispose();
    super.dispose();
  }

Create a new file and add this modified version of the package code. The only change is that it’s using the PageController that’s passed in vs one created internally.

import 'dart:async';

import 'package:flutter/material.dart';

class MyImageSlideshow extends StatefulWidget {
  MyImageSlideshow({
    @required this.children,
    @required this.pageController,
    this.width = double.infinity,
    this.height = 200,
    this.initialPage = 0,
    this.indicatorColor = Colors.blue,
    this.indicatorBackgroundColor = Colors.grey,
    this.onPageChanged,
  });
  final List<Widget> children;
  final double width;
  final double height;
  final int initialPage;
  final Color indicatorColor;
  final Color indicatorBackgroundColor;
  final ValueChanged<int> onPageChanged;
  final PageController pageController;

  @override
  _MyImageSlideshowState createState() => _MyImageSlideshowState();
}

class _MyImageSlideshowState extends State<MyImageSlideshow> {
  final StreamController<int> _pageStreamController =
      StreamController<int>.broadcast();

  void _onPageChanged(int value) {
    _pageStreamController.sink.add(value);
    if (widget.onPageChanged != null) {
      widget.onPageChanged(value);
    }
  }

  Widget _indicator(BuildContext context) {
    return Wrap(
      spacing: 4,
      runSpacing: 4,
      alignment: WrapAlignment.center,
      children: List<Widget>.generate(
        widget.children.length,
        (index) {
          return StreamBuilder<int>(
            initialData: widget.pageController.initialPage,
            stream: _pageStreamController.stream.where(
              (pageIndex) {
                return index >= pageIndex - 1 && index <= pageIndex + 1;
              },
            ),
            builder: (_, AsyncSnapshot<int> snapshot) {
              return Container(
                width: 6,
                height: 6,
                decoration: ShapeDecoration(
                  shape: CircleBorder(),
                  color: snapshot.data == index
                      ? widget.indicatorColor
                      : widget.indicatorBackgroundColor,
                ),
              );
            },
          );
        },
      ),
    );
  }

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    _pageStreamController.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: widget.width,
      height: widget.height,
      child: Stack(
        children: [
          PageView.builder(
            onPageChanged: _onPageChanged,
            itemCount: widget.children.length,
            controller: widget.pageController,
            itemBuilder: (context, index) {
              return widget.children[index];
            },
          ),
          Positioned(
            left: 0.0,
            right: 0.0,
            bottom: 10.0,
            child: _indicator(context),
          ),
        ],
      ),
    );
  }
}

Then on your page use the new custom MyImageSlideshow instead with the added GestureDetectors.

MyImageSlideshow(
      pageController: _pageController,
      width: 400,
      height: 800,
      initialPage: 0,
      indicatorColor: HexColor("#ff9900"),
      indicatorBackgroundColor: Colors.grey,
      children: [
        GestureDetector(
          // this is where you're animating to the next picture
          onTap: () {
            if (_pageController.hasClients) {
              _pageController.animateToPage(
                1,
                duration: const Duration(milliseconds: 400),
                curve: Curves.easeInOut,
              );
            }
          },
          child: Image.asset(
            'third.png',
            fit: BoxFit.cover,
          ),
        ),
        GestureDetector(
          onTap: () {
            if (_pageController.hasClients) {
              _pageController.animateToPage(
                2,
                duration: const Duration(milliseconds: 400),
                curve: Curves.easeInOut,
              );
            }
          },
          child: Image.asset(
            'second.png',
            fit: BoxFit.cover,
          ),
        ),
        GestureDetector(
          onTap: () {
            if (_pageController.hasClients) {
              _pageController.animateToPage(
                0, // going back to first picture
                duration: const Duration(milliseconds: 400),
                curve: Curves.easeInOut,
              );
            }
          },
          child: Image.asset(
            'first.png',
            fit: BoxFit.cover,
          ),
        ),
      ],
      onPageChanged: (value) {
        print('Page changed: $value');
      },
    )

That should do it for ‘ya.

Answered By – Loren.A

Answer Checked By – Jay B. (FlutterFixes Admin)

Leave a Reply

Your email address will not be published.