Flutter中的轮动图以及抖音上下滑页切换视频功能等等,这些都可以通过 PageView 轻松实现
PageView常见属性:
PageView 的使用
class MyPage extends StatefulWidget { const MyPage({super.key}); @override State<MyPage> createState() => _MyPageState(); } class _MyPageState extends State<MyPage> { @override Widget build(BuildContext context) { return Scaffold( body: PageView( scrollDirection: Axis.vertical, //垂直滑动 默认水平滑动 children: const [ Center( child: Text("1"), ), Center( child: Text("2"), ), Center( child: Text("3"), ), Center( child: Text("4"), ), ], )); } }
PageView.builder
class MyPage extends StatefulWidget { const MyPage({super.key}); @override State<MyPage> createState() => _MyPageState(); } class _MyPageState extends State<MyPage> { @override Widget build(BuildContext context) { return Scaffold( body: PageView.builder( itemCount: 5, scrollDirection: Axis.vertical, // 滑动方向为垂直方向 itemBuilder: (BuildContext context, int index) { return Center( child: Text("第$index页"), ); }, )); } }
PageView上拉无限加载的实现思路
class PageViewPage extends StatefulWidget { const PageViewPage({super.key}); @override State<PageViewPage> createState() => _PageViewPageState(); } class _PageViewPageState extends State<PageViewPage> { final List<Widget> _list = []; // 创建一个名为_list的空Widget列表 @override void initState() { // 在初始化阶段运行 super.initState(); for (var i = 0; i < 3; i++) { _list.add(MyPage(text: "$i")); // 将一个带有相应文本的MyPage小部件添加到_list中 } } @override Widget build(BuildContext context) { return Scaffold( body: PageView( scrollDirection: Axis.vertical, // 设置PageView的滚动方向为垂直方向 onPageChanged: (index) { // 每当页面更改时调用的回调函数 print("-----$index"); // 打印当前页面的索引 print(_list.length); // 打印_list中的部件数 if (index + 1 == _list.length) { // 如果当前页面是_list的倒数第二个 setState(() { // 在setState中更改_list for (var i = 0; i < 3; i++) { // 添加10个新的MyPage小部件到_list中 _list.add(MyPage(text: "$i")); } }); } }, children: _list, // 将_list中的小部件作为PageView的子部件 )); } } class MyPage extends StatefulWidget { final String text; const MyPage({super.key, required this.text}); @override State<MyPage> createState() => _MyPageState(); } class _MyPageState extends State<MyPage> { @override Widget build(BuildContext context) { return Center( child: Text(widget.text, style: Theme.of(context).textTheme.headline1), // 显示小部件的文本 ); } }
PageView 实现一个无限轮播的轮播图
import 'package:flutter/material.dart'; class PageViewPage extends StatefulWidget { const PageViewPage({super.key}); // PageViewPage组件的构造函数 @override State<PageViewPage> createState() => _PageViewPageState(); // 创建并返回PageViewPage组件对应的状态 } class _PageViewPageState extends State<PageViewPage> { List<Widget> pageList = []; // 定义一个Widget类型的列表pageList @override void initState() { super.initState(); // 重写父类的initState()函数 List listData = [ // 创建一个列表listData包含多个图片URL { "imageUrl": 'https://www.itying.com/images/flutter/1.png', }, { "imageUrl": 'https://www.itying.com/images/flutter/2.png', }, { "imageUrl": 'https://www.itying.com/images/flutter/3.png', }, ]; for (int i = 0; i < listData.length; ++i) { // 遍历listData pageList.add(PicturePage( url: listData[i]["imageUrl"], )); // 根据遍历结果创建PicturePage组件,并将其添加到pageList列表中 } } @override Widget build(BuildContext context) { // 重写父类的build()函数 return Scaffold( body: ListView( // 在Scaffold的主体部分创建一个ListView组件 children: [Swiper(pageList: pageList)], // 将Swiper组件添加到ListView的子部件列表中 ), ); } } //Swiper组件 class Swiper extends StatefulWidget { final double width; final double height; final List<Widget> pageList; const Swiper( {super.key, this.width = double.infinity, this.height = 200, required this.pageList}); @override State<Swiper> createState() => _SwiperState(); } class _SwiperState extends State<Swiper> { int _currentPageIndex = 0; @override void initState() { super.initState(); } @override Widget build(BuildContext context) { return Stack( children: [ SizedBox( width: double.infinity, height: 200, child: PageView.builder( onPageChanged: (int index) { // 当页面改变时调用的回调函数 setState(() { _currentPageIndex = index % (widget.pageList.length); }); }, itemCount: 10000, // 打算生成的页面数,这里写得非常大,因此可以实现无限循环滚动 itemBuilder: (context, index) { return widget.pageList[index % (widget.pageList.length)]; }), ), Positioned( //圆点 bottom: 10, //位置 left: 0, //位置 right: 0, //位置 child: Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(widget.pageList.length, (i) { // 利用List.generate方法生成指定数量的圆点 return Container( margin: const EdgeInsets.fromLTRB(2, 0, 2, 0), width: 10, height: 10, decoration: BoxDecoration( shape: BoxShape.circle, color: _currentPageIndex == i ? Colors.blue : Colors.grey), ); }).toList(), ), ), ], ); } } // PicturePage 图片页面 class PicturePage extends StatefulWidget { final String url; final double width; final double height; const PicturePage( {super.key, required this.url, this.width = double.infinity, this.height = 200}); @override State<PicturePage> createState() => _PicturePageState(); } class _PicturePageState extends State<PicturePage> { @override Widget build(BuildContext context) { print(widget.url); return SizedBox( width: widget.width, height: widget.height, child: Image.network(widget.url, fit: BoxFit.cover), ); } }
controller 里的PageContrpller 参数
PageController
类的构造函数有几个参数,它们允许您对页面视图的行为进行自定义。下面是PageController
类的构造函数及其参数:
PageController({ double initialPage = 0.0, bool keepPage = true, double viewportFraction = 1.0, bool allowImplicitScrolling = false, double? scrollingThreshold, List<PageMetricsListener>? listeners, })
initialPage
: 初始页面的索引,默认为0。这确定了页面视图的初始位置。keepPage
: 当keepPage
为true时,PageController
会记住用户手动滑动到的页面,并在dispose()
方法调用后仍然保持在那个页面。默认为true。viewportFraction
: 页面视图的每个页面的可见部分的比例。默认为1.0,表示整个页面都可见。可以设置为小于1的值,以显示部分页面,类似于Carousel。allowImplicitScrolling
: 当用户在滚动视图时是否允许PageController
隐式滚动到相应的位置。默认为false。如果设置为true,PageController
将在页面视图发生变化时自动滚动到当前页面。scrollingThreshold
: 一个可选的阈值,用于确定何时更新监听器的事件。默认情况下,PageController
将在页面滚动了10%或更多时触发监听器。listeners
: 一个PageMetricsListener
类型的列表,用于监听页面滚动的事件。您可以通过添加监听器来监听页面视图的滚动事件