简介
PageView 是 Flutter 中用于创建可滑动页面的组件,可以实现类似轮播图、引导页等效果。它支持水平和垂直方向的滑动,并且可以自定义滑动效果。
基本用法
PageView(
children: <Widget>[
Container(
color: Colors.red,
child: Center(child: Text('Page 1')),
),
Container(
color: Colors.green,
child: Center(child: Text('Page 2')),
),
Container(
color: Colors.blue,
child: Center(child: Text('Page 3')),
),
],
)
构建方式
PageView.builder
适用于大量页面的情况。
PageView.builder(
itemCount: 10,
itemBuilder: (context, index) {
return Container(
color: Colors.primaries[index % Colors.primaries.length],
child: Center(
child: Text('Page $index'),
),
);
},
)
PageView.custom
自定义页面构建方式。
PageView.custom(
childrenDelegate: SliverChildBuilderDelegate(
(context, index) {
return Container(
color: Colors.primaries[index % Colors.primaries.length],
child: Center(
child: Text('Page $index'),
),
);
},
childCount: 10,
),
)
常用属性
scrollDirection
滚动方向。
controller
页面控制器。
onPageChanged
页面切换回调。
pageSnapping
是否自动对齐到页面边界。
使用场景
- 引导页
- 轮播图
- 图片查看器
- 卡片切换
完整示例
class PageViewDemo extends StatefulWidget {
@override
_PageViewDemoState createState() => _PageViewDemoState();
}
class _PageViewDemoState extends State<PageViewDemo> {
final PageController _controller = PageController(initialPage: 0);
int _currentPage = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('PageView Demo'),
),
body: Stack(
children: [
PageView.builder(
controller: _controller,
onPageChanged: (int page) {
setState(() {
_currentPage = page;
});
},
itemCount: 5,
itemBuilder: (context, index) {
return Container(
color: Colors.primaries[index % Colors.primaries.length],
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.image,
size: 100,
color: Colors.white,
),
SizedBox(height: 16),
Text(
'Page ${index + 1}',
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
],
),
),
);
},
),
Positioned(
bottom: 20,
left: 0,
right: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(5, (index) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 4),
width: 8,
height: 8,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _currentPage == index
? Colors.white
: Colors.white.withOpacity(0.4),
),
);
}),
),
),
],
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
进阶用法
1. 无限滚动
class InfinitePageView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return PageView.builder(
itemBuilder: (context, index) {
final actualIndex = index % 3; // 实际只有3个页面
return Container(
color: Colors.primaries[actualIndex],
child: Center(
child: Text('Page $actualIndex'),
),
);
},
);
}
}
2. 视差效果
class ParallaxPageView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return PageView.builder(
itemCount: 5,
itemBuilder: (context, index) {
return Stack(
children: [
// 背景层
ParallaxBackground(index: index),
// 内容层
Positioned.fill(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Page $index',
style: TextStyle(
color: Colors.white,
fontSize: 24,
),
),
],
),
),
],
);
},
);
}
}
性能优化建议
- 使用 PageView.builder 而不是默认构造函数
- 合理使用 keepPage 属性
- 避免在页面中进行复杂计算
- 及时释放资源
注意事项
- 注意内存管理
- 处理好页面的状态管理
- 注意控制器的释放
- 合理设置缓存页面数量
实战案例:轮播图到底要不要自己写 PageView
我在电商项目的首页轮播上做过一个很实际的取舍:pubspec 里已经有 carousel_slider(部分电商 App 核实过的依赖),首页 Banner 直接用它,一行配置就有自动播放和指示器;但引导页、图片查看器这类”纯分页”场景,我反而坚持用原生 PageView。理由很现实:carousel_slider 本质是对 PageView 的二次封装,多一层依赖就多一层版本绑定的风险——我在 flutter_brightness 里就吃过 win32 与 ffi 版本强绑定的亏,简单分页不值得再引入一层。原生 PageView 的坑主要在控制器:PageController 要记得 dispose,切页面多了不释放会泄漏;页面数量大时用 PageView.builder 按需构建,和 ListView.builder 一个道理。另外 onPageChanged 里做 setState 更新指示器小圆点时,别在里面再触发耗时的网络请求,滑动会掉帧。
参考:Flutter 官方文档(api.flutter.dev)PageView 类。
总结
PageView 是一个强大的页面切换组件,通过合理配置可以实现各种炫酷的切换效果。在使用时需要注意性能优化和内存管理。
