'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.
Solution 1:[1]
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)),
);
},
),
),
]);
}
}
Solution 2:[2]
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)),
);
},
),
),
]);
}
Solution 3:[3]
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
),
]);
}
Solution 4:[4]
Vertical Indicators On Slider or Flutter Carousel
class VerticalSlider extends StatefulWidget {
@override
_VerticalSliderState createState() => _VerticalSliderState();
}
class _VerticalSliderState extends State<VerticalSlider> {
List imageSliders=[
//add your items here
];
int _current = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Vertical sliding carousel ')),
body: Stack(
children: [
Container(
child: CarouselSlider(
options: CarouselOptions(
viewportFraction: .6,
aspectRatio: 1.2,
enlargeCenterPage: true,
scrollDirection: Axis.vertical,
autoPlay: true,
onPageChanged: (index, reason) {
setState(() {
_current = index;
});
}
),
items: imageSliders,
)
),
Positioned(
top: 50,
right: 10,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: imgList.map((url) {
int index = imgList.indexOf(url);
return Container(
width: 8.0,
height: 8.0,
margin: EdgeInsets.symmetric(vertical: 4.0, horizontal: 2.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _current == index
? Colors.white60
: Color.fromRGBO(0, 0, 0, 0.4),
),
);
}).toList(),
),
),
],
),
);
}
}
And you may add custom indicators too.
Solution 5:[5]
The easiest way is to use CarouselSlider
with the AnimatedSmoothIndicator
widget
int _current = 0;
@override
Widget build(BuildContext context) {
Column(children: [
CarouselSlider(
options: CarouselOptions(
height: MediaQuery.of(context).size.height / 2,
onPageChanged: (i, r) {
setState(() {
_current = i;
});
}),
items: imageList.map((e) => Container(
child: Image.network(e, fit: BoxFit.cover),
))
.toList(),
),
Container(
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0),
child: AnimatedSmoothIndicator(
activeIndex: _current,
count: imageList.length,
effect: ExpandingDotsEffect(
activeDotColor: Color.fromRGBO(0, 0, 0, 0.9),
dotWidth: 8,
dotHeight: 8),
),
)
]);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | chunhunghan |
Solution 2 | Balaji Rathakrishnan |
Solution 3 | Vinicius Alcantara |
Solution 4 | FEELIX |
Solution 5 | Krishna Acharya |