美文网首页
7.PageView与页面缓存

7.PageView与页面缓存

作者: ankouyang | 来源:发表于2022-09-28 10:03 被阅读0次

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,下面有很多频道页,如果不支持页面缓存,则一旦滑到新的频道旧的频道页就会销毁,滑回去时又得重新请求数据和构建页面,这谁扛得住!
所以具体的我们看下一节可滚动组件缓存。

相关文章

网友评论

      本文标题:7.PageView与页面缓存

      本文链接:https://www.haomeiwen.com/subject/atubortx.html