Flutter 水平列表视图点指示器

Posted

技术标签:

【中文标题】Flutter 水平列表视图点指示器【英文标题】:Flutter Horizontal List View Dot Indicator 【发布时间】:2019-12-27 23:53:15 【问题描述】:

我有多个图像,每个图像都有自己的重定向链接。目前,这在使用列表视图构建显示手势检测器内的图像时效果很好。

不过,我想添加一个点指示符来显示正在查看的图像。如何获取正在显示的图像的索引?或在向左或向右滑动时增加/减少计数器。

我研究过轮播,但它们似乎不允许每张图片重定向到其他地方。

【问题讨论】:

您能分享一下代码,展示您到目前为止所做的尝试,以便我们轻松帮助您吗? 【参考方案1】:

根据上面 cmets 中 @chunhunghan 所指的示例,您需要替换 map<Widget> ( (image, url) ..imgList.map((image) int index = imgList.indexOf(image); ..

我能够让它与上述更改一起工作。修改了 build 方法的代码 sn-p:

  @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)),
            );
          ,
        ),
      ),
    ]);
  

【讨论】:

【参考方案2】:

如果我明白你的意思。带包https://pub.dev/packages/carousel_slider 向左或向右滑动图像可以从 onPageChanged 事件中获取当前页面 并使用 InkWell 包装图像,您可以导航到其他页面。在我的演示中,只需打印点击消息

代码sn-p

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

【讨论】:

什么是 map 因为它给了我一个错误 @VipulChauhan it' 来自官方示例 github.com/serenader2014/flutter_carousel_slider/blob/master/… ,您可以将您的代码发布到另一个问题吗?谢谢。 感谢您的回复,但我通过轮播滑块和点指示器找到了答案 @VipulChauhan 解决方案是什么?也得到The method 'map' isn't defined for the class 地图出错了,请问你是怎么写的?【参考方案3】:

我找到的解决方案,除了将map改成使用imgList,就是把.toList()放在imgList.map函数返回,如下:

@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
      ),
    ]);
  

【讨论】:

谢谢!为此【参考方案4】:

滑块或颤振轮播上的垂直指示器


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

您也可以添加自定义指标。

【讨论】:

以上是关于Flutter 水平列表视图点指示器的主要内容,如果未能解决你的问题,请参考以下文章

UITableView 水平滚动指示器

Flutter Spinkit 进度指示器

如何在可展开的列表视图中设置不同的组指示器图像?

如何为每个页面加载颤动在 Web 视图中实现进度指示器?

如何在 Flutter 中更改 Swiper 分页颜色?

没有 NavigationLink 的 SwiftUI 列表披露指示器