我们在短视频应用中经常会看到不停上滑浏览下一条视频的沉浸式交互效果,这种交互能够让用户不停地翻页,直到找到喜欢的视频内容,从而营造一种不断“搜寻目标”的感觉,让用户欲罢不能。这种交互形式在 Flutter 中可以轻松使用 PageView
组件实现。
![上滑交互.gif](https://img-blog.csdnimg.cn/img_convert/c5b78397f8d4fb467aa8ca0669d67d4d.gif#clientId=u59a471d5-0fad-4&crop=0&crop=0&crop=1&crop=1&from=ui&id=u9f191d78&margin=[object Object]&name=上滑交互.gif&originHeight=464&originWidth=268&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1442042&status=done&style=none&taskId=u45384ae2-6df3-471a-a2f8-ba3375c5590&title=)
PageView
组件专门设计用来实现翻页效果,类定义如下:
PageView({
Key? key,
this.scrollDirection = Axis.horizontal,
this.reverse = false,
PageController? controller,
this.physics,
this.pageSnapping = true,
this.onPageChanged,
List<Widget> children = const <Widget>[],
this.dragStartBehavior = DragStartBehavior.start,
this.allowImplicitScrolling = false,
this.restorationId,
this.clipBehavior = Clip.hardEdge,
this.scrollBehavior,
this.padEnds = true,
})
其中常用的属性说明如下:
scrollDirection
:滑动方向,可以支持纵向翻页或横向翻页,默认是横向翻页。controller
:翻页控制器,可以通过控制器来制定初始页,以及跳转到具体的页面。onPageChanged
:翻页后的回调函数,会告知翻页后的页码。reverse
:是否反向翻页,默认是 false
。如果横向滑动翻页的话,如果开启反向翻页,则是从右到左翻页。如果是纵向翻页的话,就是从顶部到底部翻页。children
:在翻页中的组件列表,每一页都以自定义组件内容,因此这个组件也可以用于做引导页,或是类似滑动查看详情的效果。PageView
使用起来非常简单,我们先定义一个PageView
翻页的内容组件,简单地将接收的图片文件满屏显示。代码如下,实际应用的时候可以根据需要换成其他自定义组件。
class ImagePageView extends StatelessWidget {
final String imageName;
const ImagePageView({Key? key, required this.imageName}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
body: Image.asset(
imageName,
fit: BoxFit.fitHeight,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
),
);
}
}
之后是定义一个 PageViewDemo
来应用 PageView
翻页应用示例,代码如下:
class PageViewDemo extends StatefulWidget {
const PageViewDemo({Key? key}) : super(key: key);
State<PageViewDemo> createState() => _PageViewDemoState();
}
class _PageViewDemoState extends State<PageViewDemo> {
late PageController _pageController;
int _pageIndex = 1;
void initState() {
_pageController = PageController(
initialPage: _pageIndex,
viewportFraction: 1.0,
);
super.initState();
}
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: PageView(
scrollDirection: Axis.vertical,
onPageChanged: (index) {
_pageIndex = index;
},
controller: _pageController,
allowImplicitScrolling: false,
padEnds: true,
reverse: false,
children: const [
ImagePageView(imageName: 'images/earth.jpeg'),
ImagePageView(imageName: 'images/island-coder.png'),
ImagePageView(imageName: 'images/mb.jpeg'),
],
),
);
}
}
这个示例里,我们的 pageController
只是演示了设置初始页码。我们看到的 viewportFraction
可以理解为一页内容占据屏幕的比例,比如我们可以设置该数值为1/3,支持一个屏幕分段显示3个页面内容。
![分段显示.gif](https://img-blog.csdnimg.cn/img_convert/96169512a6be520047d27db20f77ed06.gif#clientId=u59a471d5-0fad-4&crop=0&crop=0&crop=1&crop=1&from=ui&id=u85e0ead3&margin=[object Object]&name=分段显示.gif&originHeight=464&originWidth=266&originalType=binary&ratio=1&rotation=0&showTitle=false&size=3729692&status=done&style=none&taskId=u7b19cb90-3b8a-4e92-a648-2c5b20b5de2&title=)
PageController
可以控制滑动到指定位置,比如我们可以调用 animateToPage
方法实现一个快速滑动到顶部的悬浮按钮。
floatingActionButton: FloatingActionButton(
onPressed: () {
_pageController.animateToPage(
0,
duration: const Duration(
milliseconds: 1000,
),
curve: Curves.easeOut,
);
},
backgroundColor: Colors.black.withAlpha(180),
child: const Icon(
Icons.arrow_upward,
color: Colors.white,
),
),
实现效果如下。
![滑动到顶部.gif](https://img-blog.csdnimg.cn/img_convert/72077914d26b45ca96224a2a02db87d5.gif#clientId=u59a471d5-0fad-4&crop=0&crop=0&crop=1&crop=1&from=ui&id=u442460b0&margin=[object Object]&name=滑动到顶部.gif&originHeight=464&originWidth=266&originalType=binary&ratio=1&rotation=0&showTitle=false&size=5170161&status=done&style=none&taskId=u01b99c82-51b3-450d-8b5c-c142b3332d8&title=)
PageController
还有如下控制翻页的方法:
jumpToPage
:跳转到指定页面,但是没有动画。注意这里不会校验页码是否会超出范围。nextPage
:滑动到下一页,实际上调用的是 animateToPage
方法。previousPage
:滑动到上一页,实际上调用的是 animateToPage
方法。本篇介绍了 Flutter 的翻页组件 PageView
的使用,通过 PageView
可以轻松实现类似短视频的纵向上滑翻页的效果,也可以实现横向翻页效果(如阅读类软件)。在接下来的系列文章中,本专栏将会介绍更多 Flutter 实用的组件。