书到用时方恨少,事非经过不知难。这篇文章主要讲述Flutter 专题108 图解 PageView 滑动页面预览小尝试 #yyds干货盘点#相关的知识,希望能为你提供帮助。
PageView 滑动页面预览应用在很多场景中,小菜之前只用过最基本的用法,今天小菜尝试系统性的学习一下 PageView 的基本应用;
PageView 一般用户少量需要滑动页面切换的场景,但整体使用很灵活,常用作切换 Tab 页或活动 Banner 等;
源码分析
PageView(
Key key,
this.scrollDirection = Axis.horizontal,// 页面滑动方向(水平/竖直)
this.reverse = false,// 是否反向滑动
PageController controller,// 页面控制器
this.physics,// 滑动到首页和末页动画效果
this.pageSnapping = true,// 是否整页滑动
this.onPageChanged,// 页面监听滑动回调
List<
Widget>
children = const <
Widget>
[],// Page 页面展示子 Widget
this.dragStartBehavior = DragStartBehavior.start,
)PageView.builder(
Key key,
this.scrollDirection = Axis.horizontal,
...
this.dragStartBehavior = DragStartBehavior.start,
)PageView.custom(
Key key,
this.scrollDirection = Axis.horizontal,
...
this.dragStartBehavior = DragStartBehavior.start,
)
分析源码可得,PageView 是一个有状态的 StatefulWidget 小部件,主要通过 PageController 和 onPageChanged 控制滑动与数据监听,并且提供了两种命名构造方法,小菜逐个学习属性特性;
案例尝试
默认构造函数 1. PageView() 小菜首先使用默认构造函数生成一个基本的 PageView;
return Container( height: 240,
child: PageView(children: <
Widget>
[
_itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3)
]));
文章图片
2. scrollDirection scrollDirection 主要用于 PageView 滑动方向,分别为 Axis.horizontal 水平方向和 Axis.vertical 竖直方向;
return Container( height: 240,
child: PageView(scrollDirection: Axis.horizontal, children: <
Widget>
[
_itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3)
]));
文章图片
3. pageSnapping pageSnapping 用于是否禁止页面捕捉,小菜理解为 Page 页面是否为整页滑动切换;当 pageSnapping=false 时,Page 页可以逐步滑动,滑动到中途一半的时候也可以停止;
return Container( height: 240,
child: PageView(pageSnapping: false, children: <
Widget>
[
_itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3)
]));
文章图片
4. reverse reverse 用于是否默认反向滑动,与 ListView 类似,PageView 默认初始从左往右或从上到下;reverse=true 即默认方向想法,为从右往左或从下往上;
return Container( height: 240,
child: PageView(reverse: true, children: <
Widget>
[
_itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3)
]));
文章图片
5. onPageChanged onPageChanged 是页面监听的回调,当页面切换时,会返回当前 Position,可以根据当前具体位置进行业务处理;
return Container( height: 240,
child: PageView(onPageChanged: (position) =>
print(Current index = $position + 1),
children: <
Widget>
[
_itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3)
]));
文章图片
6. physics physics 主要体现在首页和尾页结束时动画动画效果,为 ScrollPhysics 类型,可以自定义也可以根据 Flutter 提供的动画来处理;类似的有 ClampingScrollPhysics 和 BouncingScrollPhysics 等;
return Container( height: 240,
child: PageView(physics: BouncingScrollPhysics(), children: <
Widget>
[
_itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3)
]));
文章图片
7. controller controller 为 PageView 的控制器,可以设置页面跳转或者初始化位置,以及滑动动画效果等;
class PageController extends ScrollController
PageController(
this.initialPage = 0,
this.keepPage = true,
this.viewportFraction = 1.0,
)
简单了解 PageController 源码,主要涉及 initialPage 初始化展示的 Page 页数组下标;keepPage 是否保存数据状态;viewportFraction 为每个 Page 页占据整个 PageView 比例;
PageController 还提供了几个重要的方法,包括 animateToPage 和 jumpToPage 等进行具体 Page 页切换,与其他的 Widget 联动;
PageController _controller;
@override
void initState()
super.initState();
_controller = PageController(initialPage: 1, viewportFraction: 0.75);
return Container( height: 240,
controller: _controller, children: <
Widget>
[
_itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3)
]));
文章图片
PageView.builder PageView 提供了便利的 .builder() 构造方法,适用于大量动态或类似的 Widget,类似于 ListView.builder() 方式,注意:其中 itemCount 不可为空,当不设置 itemCount 时,PageView 会默认为无限循环,数组会一直增加;
其中当我们需要与外界其他 Widget 联动时,可通过 PageController 进行 Page 页切换或直接跳转等;
_bodyWid()
return Column(children: <
Widget>
[
Container( height: 60, color: Colors.green.withOpacity(0.8),
child: Row(children: <
Widget>
[
Expanded( child: GestureDetector(
child: Row( mainAxisAlignment: MainAxisAlignment.center,
children: <
Widget>
[
Text(目录, style: TextStyle( fontSize: 16.0, color: Colors.white)),
Icon(Icons.arrow_downward, color: Colors.white)
]),
onTap: ()
print(---GestureDetector--目录---);
setState(() );
_currentIndex = 0;
_controller.animateToPage(0, duration: Duration(milliseconds: 400), curve: Curves.easeInOut);
)),
Container(width: 0.5, color: Colors.white),
Expanded( child: GestureDetector(
child: Center( child: Text(书签, style: TextStyle( fontSize: 16.0, color: Colors.white))),
onTap: ()
print(---GestureDetector--书签---);
setState(() );
_currentIndex = 1;
_controller.animateToPage(1, duration: Duration(milliseconds: 400), curve: Curves.easeInOut);
))
])),
_leftMenuPage()
]);
_leftMenuPage()
return Expanded(
child: PageView.builder(
itemBuilder: (context, position) =>
_leftItemPage(context, position),
itemCount: 2, controller: _controller,
onPageChanged: (position)
print(PageView.onPageChanged---$position);
setState(()if (_currentIndex != position)_currentIndex = position;
);
));
文章图片
PageView.custom PageView 还提供了 .custom() 构造方法;可以通过 SliverChildBuilderDelegate 代理添加 Page 页面懒加载还可以进行 Page 页重新排列,这也是 .builder() 构造方法所不支持的;
return Container( height: 240,
child: PageView.custom(
controller: _controller,
childrenDelegate: SliverChildBuilderDelegate((BuildContext context, int index) =>
_itemTransCard(index), childCount: 4)));
_itemTransCard(index)
Matrix4 _matrix = Matrix4.identity();
print(---_itemTransCard-$_currentPageValue.floor()-);
if (index == _currentPageValue.floor())
// The Current Page Item
var currScale = 1 - (_currentPageValue - index) * (1 - _scaleFactor);
var currTrans = 240.0 * (1 - currScale) / 2;
_matrix = Matrix4.diagonal3Values(1.0, currScale, 1.0)..setTranslationRaw(0.0, currTrans, 0.0);
return Transform(transform: _matrix, child: _itemCard(index));
else if (index == _currentPageValue.floor() + 1)
// The Right Page Item
var currScale = _scaleFactor + (_currentPageValue - index + 1) * (1 - _scaleFactor);
var currTrans = 240.0 * (1 - currScale) / 2;
_matrix = Matrix4.diagonal3Values(1.0, currScale, 1.0)..setTranslationRaw(0.0, currTrans, 0.0);
return Transform(transform: _matrix, child: _itemCard(index));
else if (index == _currentPageValue.floor() - 1)
// The Left Page Item
var currScale = 1 - (_currentPageValue - index) * (1 - _scaleFactor);
var currTrans = 240.0 * (1 - currScale) / 2;
_matrix = Matrix4.diagonal3Values(1.0, currScale, 1.0)..setTranslationRaw(0.0, currTrans, 0.0);
return Transform(transform: _matrix, child: _itemCard(index));
else
// Else
_matrix = Matrix4.diagonal3Values(1.0, _scaleFactor, 1.0)..setTranslationRaw(0.0, 240.0 * (1 - _scaleFactor) / 2, 0.0);
return Transform(transform: _matrix, child: _itemCard(index));
文章图片
小菜在测试过程中,当初始化展示的 Page 页非首页时,展示效果有问题,所对应的并没有展示到该有的缩放尺寸,而依旧是默认首页是正常缩放尺寸;小菜发现,初始化时,_currentPageValue 还未从 PageController.addListener() 中监听赋值,默认为 0,因此导致展示错误,小菜对 _currentPageValue 设置初始化位置赋值即可;
var _initialIndex = 1;
var _currentPageValue = https://www.songbingjia.com/android/0.0;
@override
void initState()
super.initState();
//_controller = PageController();
_controller =
PageController(initialPage: _initialIndex, viewportFraction: 0.75);
_currentPageValue = _initialIndex * 1.0;
_controller.addListener(()
print(--CurrentPage--$_controller.page);
_currentPageValue = _controller.page;
setState(() );
);
文章图片
PageView 案例源码
【Flutter 专题108 图解 PageView 滑动页面预览小尝试 #yyds干货盘点#】 小菜对 PageView 的底层还不够深入,可以自定义很多酷炫效果,建议多多尝试;如有错误,请多多指导!
推荐阅读
- [OpenCV实战]31 使用OpenCV将一个三角形仿射变换到另一个三角形
- #yyds干货盘点# 解决剑指offer(二叉搜索树与双向链表)
- 初识C++ 函数重载以及背后的原理
- 前端(react)上传到阿里云OSS存储 实例
- 华为路由与交换综合实验案例详解 纯干货分享
- win10系统hosts文件不见了怎样办?
- win10系统如何将系统字体设置成繁体字
- win10系统如何关闭windows defender?
- win10系统开机提示mfc110u.dll失去怎样办?