有没有办法在 Flutter 中使用 PageView 进行无限循环



有没有办法在 Flutter 中使用 PageView 进行无限循环?例如,如果我的 PageView 有 5 页,则在滑动到第 5 页后,我可以再次沿同一方向滑动以到达第 1 页。

默认情况下,PageView.builder 在颤振中是无限的。除非您提供itemCount.

以下将无限打印从0到4的页面

final controller = new PageController(initialPage: 999);
 ...
new PageView.builder(
      controller: controller,
      itemBuilder: (context, index) {
        return new Center(
          child: new Text('${index % 5}'),
        );
      },
)

如果您有预定义的小部件列表,则可以使用以下方法实现连续滚动:

return PageView.builder(
  itemBuilder: (context, index) {
    return _children[index % _children.length];
  },
  controller: pageController,
);

我用这个库找到了一个很好的解决方案https://pub.dev/packages/infinity_page_view

只需导入库并使用InfinityPageView而不是PageView

InfinityPageView(
  controller: infinityPageController,
  itemCount: colorList.length,
  itemBuilder: (context, index) {
    return Container(
      color: colorList[index];
    );
  },
)

你可以实现无限使用PageView构建器滚动,而不给itemCount值,将会有无限的页面,你只需要维护将在屏幕上绘制的页面索引。

PageView.builder(
  controller: _pageController,
  scrollDirection: Axis.horizontal,
  onPageChanged: (index) {
    setState(() {
      _currentIndex = index % _walkthroughSlides.length;
    });
  },
  itemBuilder: (context, index) {
    return _walkthroughSlides[index % _walkthroughSlides.length];
  },
)

上面提到的答案会占用更多内存,这可能是冗余,当您在第一个孩子上时,您无法通过反向滚动来访问最后一个孩子

import 'package:flutter/material.dart';
import 'dart:async';
class InfiniteScroll extends StatefulWidget{
  final List<Widget> children;
  InfiniteScroll({this.children});
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _InfiniteScrollState();
  }
}
class _InfiniteScrollState extends State<InfiniteScroll>{
  List<Widget> children;
  ScrollController s;
  int _pos;
  @override
  void initState() {
    _pos=1;
    children = [widget.children[widget.children.length - 1]];
    for (int i = 0; i < widget.children.length; ++i) {
      children.add(widget.children[i]);
    }
    if (widget.children.length > 1) {
      children.add(children[1]);
    }
    s = PageController();
    super.initState();
     WidgetsBinding.instance
        .addPostFrameCallback((_){
          s.jumpTo(MediaQuery.of(context).size.width);
        });
 
  }
  
  @override
  Widget build(BuildContext context) {
    
    return PageView.builder(
      scrollDirection: Axis.horizontal,
      controller: s,
      onPageChanged: (int i) {
        setState(() {
          _pos=i+1;
        });
        if (i == children.length - 1) {
          Timer(Duration(milliseconds: 400), () {
            s.jumpTo(MediaQuery.of(context).size.width);
          });
          setState(() {
          _pos=1;
        });
        } else if (i == 0) {
          Timer(Duration(milliseconds: 400), () {
            s.jumpTo(MediaQuery.of(context).size.width * (children.length - 2));
          });
          setState(() {
            _pos=children.length-2;
          });
        }
        
      },
      itemBuilder: (BuildContext context, int index) {
        return children[index];
      },
      itemCount: children.length,
    );
  }
}

现在您可以将其用作

import 'package:flutter/material.dart';
import 'package:test1/Widgets/infinite_scroll.dart';
class CoursesPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return 
        Container(
          height: MediaQuery.of(context).size.height,
          child: 
              InfiniteScroll(
                children: <Widget>[
                  Container(
                    color: Colors.red,
                    child: Center(child: Text("1",style: TextStyle(color: Colors.white,fontSize: 50),),),
                  ),
                  Container(
                    color: Colors.black,
                    child: Center(child: Text("2",style: TextStyle(color: Colors.white,fontSize: 50),),),
                  ),
                  Container(
                    color: Colors.green,
                    child: Center(child: Text("3",style: TextStyle(color: Colors.white,fontSize: 50),),),
                  ),
                  Container(
                    color: Colors.blue,
                    child: Center(child: Text("4",style: TextStyle(color: Colors.white,fontSize: 50),),),
                  ),
                ],
              )
        );
  }
}

这是没有控制器的工作。你需要像波纹管这样的注释道具项目计数和repce索引。

PageView.builder(
  onPageChanged: (v) {
    setState(() => _currentImage = v % images.length);
  },
  scrollDirection: Axis.horizontal,
  // itemCount: images.length,
  itemBuilder: (ctx, i) {
    return CustomImageNetwork(
      width: imageSize,
      height: imageSize,
      image: images[i % images.length] ?? '',
    );
  },
)

在remi解决方案旁边使用扩展

extension ListX<E> on List {
  E loop(int index) => this[index % length];
}
class _CarouselWidgetState extends State<CarouselWidget> {
  late final List<Widget> children;
  late final PageController controller;
  @override
  initState() {
    super.initState();
    children = widget.children;
    controller = PageController(initialPage: 100);
  }
  @override
  Widget build(BuildContext context) {
    return PageView.builder(
      controller: controller,
      // itemCount: children.length,
      itemBuilder: (context, pagePosition) {
        return children.loop(pagePosition)
      },
    );
  }
}

您可以使用"OverScroll通知程序"和PageController controller.jumpToPage((将当前页面更改为最后一页或第一页,具体取决于我们"过度滚动"的边缘。

class CarousselView extends StatefulWidget {
const CarousselView({super.key});
@override
State<CarousselView> createState() => _CarousselViewState();
}
class _CarousselViewState extends State<CarousselView>
with SingleTickerProviderStateMixin {
 int _index = 1;
 TabController? controller;
 late PageController _controller;
 String message = "";
  @override
 void initState() {
 controller = TabController(
  length: 6,
  vsync: this,
   );
  _controller = PageController();
 }
@override
Widget build(BuildContext context) {
 return Stack(
   children: [
    NotificationListener<OverscrollIndicatorNotification>(
      onNotification: ((notification) {
        print("Oversrolled");
        setState(() {
          _controller.jumpToPage(_index == 0 ? 5 : 0);
        });
        return true;
      }),
      child: PageView.builder(
        scrollDirection: Axis.horizontal,
        itemCount: 6,
        controller: _controller,
        onPageChanged: (int index) => setState(() {
          controller!.index = index;
          _index = index;
        }),
        itemBuilder: (_, i) {
          return Card(
            elevation: 6,
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(20)),
            child: Center(
              child: Text(
                "Card ${i}",
                style: TextStyle(fontSize: 32),
              ),
            ),
          );
        },
      ),
    ),
    Container(
      alignment: Alignment.bottomCenter,
      child: TabPageSelector(
        indicatorSize: 6.0,
        controller: controller,
         ),
        )
       ],
     );
   }
 }
final controller = new PageController(initialPage: children.length*999);
PageView.builder(
  controller: controller,
  itemBuilder: (context, index) {
    return new Center(
      child: new Text('${index % children.length}'),
    );
  },

(

最新更新