1.PageView
如果要实现页面切换和 Tab 布局,我们可以使用 PageView 组件。需要注意,PageView 是一个非常重要的组件,因为在移动端开发中很常用,比如大多数 App 都包含 Tab 换页效果、图片轮动以及抖音上下滑页切换视频功能等等,这些都可以通过 PageView 轻松实现。
PageView({
Key? key,
this.scrollDirection = Axis.horizontal, // 滑动方向
this.reverse = false,
PageController? controller,
this.physics,
List<Widget> children = const <Widget>[],
this.onPageChanged,
//每次滑动是否强制切换整个页面,如果为false,则会根据实际的滑动距离显示页面
this.pageSnapping = true,
//主要是配合辅助功能用的,后面解释
this.allowImplicitScrolling = false,
//后面解释
this.padEnds = true,
})
我们看一个简单的例子
PageView(
children: [
Container(
constraints: const BoxConstraints.expand(),
color: Colors.cyanAccent,
child: const Center(child: Text('page1',textScaleFactor: 5))
),
Container(
constraints: const BoxConstraints.expand(),
color: Colors.red,
child: const Center(child: Text('page2',textScaleFactor: 5))
),
Container(
constraints: const BoxConstraints.expand(),
color: Colors.blue,
child: const Center(child: Text('page3',textScaleFactor: 5))
),
Container(
constraints: const BoxConstraints.expand(),
color: Colors.orange,
child: const Center(child: Text('page4',textScaleFactor: 5))
),
],
),
效果图(水平方向)
//设置滑动方向
scrollDirection: Axis.vertical,
竖直方向效果图
1.PageView.builder
用于创建大量或无限的子控件,代码示例:
import 'package:flutter/material.dart';
import 'package:flutter_os_china/constants/constants.dart';
class PageViewWidget extends StatefulWidget {
const PageViewWidget({Key? key}) : super(key: key);
@override
State<PageViewWidget> createState() => _PageViewWidgetState();
}
class _PageViewWidgetState extends State<PageViewWidget> {
List<BottomNavigationBarItem> navigationIconViews= const[
BottomNavigationBarItem(icon: Icon(Icons.access_time,color: Colors.grey),activeIcon:Icon(Icons.access_time,color: AppColor.primaryColor),label: 'page1'),
BottomNavigationBarItem(icon: Icon(Icons.accessibility_sharp,color: Colors.grey),activeIcon:Icon(Icons.accessibility_sharp,color: AppColor.primaryColor),label: 'page2'),
BottomNavigationBarItem(icon: Icon(Icons.scale,color: Colors.grey),activeIcon:Icon(Icons.scale,color: AppColor.primaryColor),label: 'page3'),
BottomNavigationBarItem(icon: Icon(Icons.access_alarm,color: Colors.grey),activeIcon:Icon(Icons.access_alarm,color: AppColor.primaryColor),label: 'page4'),
BottomNavigationBarItem(icon: Icon(Icons.settings_accessibility_sharp,color: Colors.grey),activeIcon:Icon(Icons.settings_accessibility_sharp,color: AppColor.primaryColor),label: 'page5'),
];
int activeIndex = 0;
// 定义各个滚PageView控制器
late PageController pageController;
@override
void initState() {
// TODO: implement initState
super.initState();
// initialPage初始化页面
pageController = PageController(initialPage: activeIndex);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('PageView'),
),
body: PageView.builder(
itemCount: 5,
controller: pageController,
scrollDirection: Axis.vertical,
itemBuilder: (context,index){
return Container(
constraints: const BoxConstraints.expand(),
color: index%2 == 0?Colors.cyanAccent:Colors.red,
child: Center(child: Text('page${index+1}',textScaleFactor: 5))
);
},
onPageChanged: (int index){
setState(() {
activeIndex = index;
});
},
),
bottomNavigationBar: BottomNavigationBar(
items: navigationIconViews,
type:BottomNavigationBarType.fixed,
onTap: (index){
setState(() {
activeIndex = index;
});
//滑动到指定的页面
pageController.animateToPage(activeIndex,duration:const Duration(milliseconds: 100),curve: Curves.ease);
},
currentIndex: activeIndex,
),
);
}
//普通的PageView
PageView buildPageView() {
return PageView(
scrollDirection: Axis.vertical,
children: [
Container(
constraints: const BoxConstraints.expand(),
color: Colors.cyanAccent,
child: const Center(child: Text('page1',textScaleFactor: 5))
),
Container(
constraints: const BoxConstraints.expand(),
color: Colors.red,
child: const Center(child: Text('page2',textScaleFactor: 5))
),
Container(
constraints: const BoxConstraints.expand(),
color: Colors.blue,
child: const Center(child: Text('page3',textScaleFactor: 5))
),
Container(
constraints: const BoxConstraints.expand(),
color: Colors.orange,
child: const Center(child: Text('page4',textScaleFactor: 5))
),
],
);
}
}
效果
2.页面缓存
我们在运行上面示例时,读者可能已经发现:每当页面切换时都会触发新 Page 页的 build,比如我们从第一页滑到第二页,然后再滑回第一页时,控制台打印如下
flutter: build 0
flutter: build 1
flutter: build 0
可见 PageView 默认并没有缓存功能,一旦页面滑出屏幕它就会被销毁,这和我们前面讲过的 ListView/GridView 不一样,在创建 ListView/GridView 时我们可以手动指定 ViewPort 之外多大范围内的组件需要预渲染和缓存(通过 cacheExtent 指定),只有当组件滑出屏幕后又滑出预渲染区域,组件才会被销毁,但是不幸的是 PageView 并没有 cacheExtent 参数!但是在真实的业务场景中,对页面进行缓存是很常见的一个需求,比如一个新闻 App,下面有很多频道页,如果不支持页面缓存,则一旦滑到新的频道旧的频道页就会销毁,滑回去时又得重新请求数据和构建页面,这谁扛得住!
所以具体的我们看下一节可滚动组件缓存。












网友评论