Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter Horizontal List View Dot Indicator

I have multiple images each with their own redirect link. Currently this works fine at displaying using a list view build to display the images inside a gesture detector.

However, I’d like to add a dot indicator to show which image is being viewed. How can I get the index of the image being displayed? Or increase / decrease a counter when swiping left or right.

I’ve looked into carousels but they don’t seem to allow each image to redirect to somewhere else.

like image 855
Bollie Avatar asked Aug 22 '19 15:08

Bollie


3 Answers

As per example pointed to by @chunhunghan above in the comments, you need to replace map<Widget> ( (image, url) {..} with imgList.map((image) {int index = imgList.indexOf(image); ..}

I was able to get it to work with the above change. Revised code snippet for the build method:

  @override
  Widget build(BuildContext context) {
    return Column(children: [
      CarouselSlider(
        items: child,
        autoPlay: false,
        enlargeCenterPage: true,
        aspectRatio: 2.0,
        onPageChanged: (index) {
          setState(() {
            _current = index;
            print("${_current}");
          });
        },
      ),
      Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: imgList.map((image) {       //these two lines 
            int index=imgList.indexOf(image); //are changed
            return Container(
              width: 8.0,
              height: 8.0,
              margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0),
              decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  color: _current == index
                      ? Color.fromRGBO(0, 0, 0, 0.9)
                      : Color.fromRGBO(0, 0, 0, 0.4)),
            );
          },
        ),
      ),
    ]);
  }
like image 122
Balaji Rathakrishnan Avatar answered Nov 06 '22 20:11

Balaji Rathakrishnan


If I understand you clear. with package https://pub.dev/packages/carousel_slider swipe image to left or right can get current page from onPageChanged event
and use InkWell wrap image, you can navigate to other page. In my demo just print click message

code snippet

final List child = map<Widget>(
  imgList,
  (index, i) {
    return Container(
      margin: EdgeInsets.all(5.0),
      child: ClipRRect(
        borderRadius: BorderRadius.all(Radius.circular(5.0)),
        child: Stack(children: <Widget>[
          InkWell(
              onTap: () { print("you click  ${index} "); },
              child: Image.network(i, fit: BoxFit.cover, width: 1000.0)),
          Positioned(
            bottom: 0.0,
            left: 0.0,
            right: 0.0,
            child: Container(
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  colors: [Color.fromARGB(200, 0, 0, 0), Color.fromARGB(0, 0, 0, 0)],
                  begin: Alignment.bottomCenter,
                  end: Alignment.topCenter,
                ),
              ),
              padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
              child: Text(
                'No. $index image',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 20.0,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ),
          ),
        ]),
      ),
    );
  },
).toList();

...

class _CarouselWithIndicatorState extends State<CarouselWithIndicator> {
  int _current = 0;

  @override
  Widget build(BuildContext context) {
    return Column(children: [
      CarouselSlider(
        items: child,
        autoPlay: false,
        enlargeCenterPage: true,
        aspectRatio: 2.0,
        onPageChanged: (index) {
          setState(() {
            _current = index;
            print("${_current}");
          });
        },
      ),
      Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: map<Widget>(
          imgList,
          (index, url) {
            return Container(
              width: 8.0,
              height: 8.0,
              margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0),
              decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  color: _current == index
                      ? Color.fromRGBO(0, 0, 0, 0.9)
                      : Color.fromRGBO(0, 0, 0, 0.4)),
            );
          },
        ),
      ),
    ]);
  }
}

enter image description here

like image 7
chunhunghan Avatar answered Nov 06 '22 18:11

chunhunghan


The solution I found, besides change map to use imgList, was to put .toList() at the imgList.map function return as follows:

@override
   Widget build(BuildContext context) {
    return Column(children: [
      CarouselSlider(
        items: child,
        autoPlay: false,
        enlargeCenterPage: true,
        aspectRatio: 2.0,
        onPageChanged: (index) {
          setState(() {
            _current = index;
            print("${_current}");
          });
        },
      ),
      Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: imgList.map((image) {     
            int index=imgList.indexOf(image);
            return Container(
              width: 8.0,
              height: 8.0,
              margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0),
              decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  color: _current == index
                      ? Color.fromRGBO(0, 0, 0, 0.9)
                      : Color.fromRGBO(0, 0, 0, 0.4)
              ),
            );
          },
        ).toList(), // this was the part the I had to add
      ),
    ]);
  }
like image 7
Vinicius Alcantara Avatar answered Nov 06 '22 19:11

Vinicius Alcantara