热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Flutter108:图解PageView滑动页面预览小尝试

      PageView滑动页面预览应用在很多场景中,小菜之前只用过最基本的用法,今天小菜尝试系统性的学习一下PageView

      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 children = const [], // 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 小部件,主要通过 PageControlleronPageChanged 控制滑动与数据监听,并且提供了两种命名构造方法,小菜逐个学习属性特性;

案例尝试

默认构造函数

1. PageView()

      小菜首先使用默认构造函数生成一个基本的 PageView

return Container( height: 240, child: PageView(children: [ _itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3) ]));

Flutter 108: 图解 PageView 滑动页面预览小尝试
2. scrollDirection

      scrollDirection 主要用于 PageView 滑动方向,分别为 Axis.horizontal 水平方向和 Axis.vertical 竖直方向;

return Container( height: 240, child: PageView(scrollDirection: Axis.horizontal, children: [ _itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3) ]));

Flutter 108: 图解 PageView 滑动页面预览小尝试
3. pageSnapping

      pageSnapping 用于是否禁止页面捕捉,小菜理解为 Page 页面是否为整页滑动切换;当 pageSnapping=false 时,Page 页可以逐步滑动,滑动到中途一半的时候也可以停止;

return Container( height: 240, child: PageView(pageSnapping: false, children: [ _itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3) ]));

Flutter 108: 图解 PageView 滑动页面预览小尝试
4. reverse

      reverse 用于是否默认反向滑动,与 ListView 类似,PageView 默认初始从左往右或从上到下;reverse=true 即默认方向想法,为从右往左或从下往上;

return Container( height: 240, child: PageView(reverse: true, children: [ _itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3) ]));

Flutter 108: 图解 PageView 滑动页面预览小尝试
5. onPageChanged

      onPageChanged 是页面监听的回调,当页面切换时,会返回当前 Position,可以根据当前具体位置进行业务处理;

return Container( height: 240, child: PageView(onPageChanged: (position) => print('Current index = ${position + 1}'), children: [ _itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3) ]));

Flutter 108: 图解 PageView 滑动页面预览小尝试
6. physics

      physics 主要体现在首页和尾页结束时动画动画效果,为 ScrollPhysics 类型,可以自定义也可以根据 Flutter 提供的动画来处理;类似的有 ClampingScrollPhysicsBouncingScrollPhysics 等;

return Container( height: 240, child: PageView(physics: BouncingScrollPhysics(), children: [ _itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3) ]));

Flutter 108: 图解 PageView 滑动页面预览小尝试
7. controller

      controllerPageView 的控制器,可以设置页面跳转或者初始化位置,以及滑动动画效果等;

class PageController extends ScrollController { PageController({ this.initialPage = 0, this.keepPage = true, this.viewportFraction = 1.0, }) }

      简单了解 PageController 源码,主要涉及 initialPage 初始化展示的 Page 页数组下标;keepPage 是否保存数据状态;viewportFraction 为每个 Page 页占据整个 PageView 比例;

      PageController 还提供了几个重要的方法,包括 animateToPagejumpToPage 等进行具体 Page 页切换,与其他的 Widget 联动;

PageController _controller; @override void initState() { super.initState(); _cOntroller= PageController(initialPage: 1, viewportFraction: 0.75); } return Container( height: 240, controller: _controller, children: [ _itemCard(0), _itemCard(1), _itemCard(2), _itemCard(3) ]));

Flutter 108: 图解 PageView 滑动页面预览小尝试

PageView.builder

      PageView 提供了便利的 .builder() 构造方法,适用于大量动态或类似的 Widget,类似于 ListView.builder() 方式,注意:其中 itemCount 不可为空,当不设置 itemCount 时,PageView 会默认为无限循环,数组会一直增加;

      其中当我们需要与外界其他 Widget 联动时,可通过 PageController 进行 Page 页切换或直接跳转等;

_bodyWid() { return Column(children: [ Container( height: 60, color: Colors.green.withOpacity(0.8), child: Row(children: [ Expanded( child: GestureDetector( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ 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; } }); })); }

Flutter 108: 图解 PageView 滑动页面预览小尝试

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)); } }

Flutter 108: 图解 PageView 滑动页面预览小尝试

      小菜在测试过程中,当初始化展示的 Page 页非首页时,展示效果有问题,所对应的并没有展示到该有的缩放尺寸,而依旧是默认首页是正常缩放尺寸;小菜发现,初始化时,_currentPageValue 还未从 PageController.addListener() 中监听赋值,默认为 0,因此导致展示错误,小菜对 _currentPageValue 设置初始化位置赋值即可;

var _initialIndex = 1; var _currentPageValue = 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(() {}); }); }

Flutter 108: 图解 PageView 滑动页面预览小尝试

      PageView 案例源码


      小菜对 PageView 的底层还不够深入,可以自定义很多酷炫效果,建议多多尝试;如有错误,请多多指导!

来源: 阿策小和尚


推荐阅读
author-avatar
情之瞬
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有