稀土掘金 稀土掘金

Flutter 中 PageView 的使用详解 | Flutter Widgets

这是我参与更文挑战的第15天,活动详情查看: 更文挑战

前言

上一篇我们聊了 IndexedStack 实现了一个简单的项目主页基础骨架的搭建,这一篇我们还是做这个主页骨架,但是是使用 PageView 来做并且附带了一些滑动效果。

看效果

先看看下面的效果一般是 App 的简单主页骨架,你知道使用 PageView 怎么实现的吗?
02.gif
这里相比上个 IndexedStack 版本有几个细节上的不同之处

  • 页面可以滑动来切换
  • 单独详情页可以改变状态并保持(count)
  • 滑动页面时导航栏也是跟着变的

PageView(页面布局)

看名字就是知道他是专门来做页面布局使用的,这篇我们要一步一步实现上面的效果,如果你看过上篇的内容了,那么这篇会快就可以学会。

主体内容

上篇我们主体内容是添加 IndexedStack ,这篇我们改变成 PageView 即可,然后会新增一个控制器和页面滑动改变后的方法实现

/// PageView 页面
class PageViewPage extends StatefulWidget {
  PageViewPage({Key? key}) : super(key: key);

  @override
  _PageViewPageState createState() => _PageViewPageState();
}

class _PageViewPageState extends State<PageViewPage> {
  // 当前子项索引
  int currentIndex = 0;
  // 子项集
  late List<Widget> children;
  // 控制器
  late PageController _controller;

  @override
  void initState() {
    super.initState();
    // 初始化子项集合
    children = [
      PageDetails(title: '首页'),
      PageDetails(title: '消息'),
      PageDetails(title: '我的'),
    ];
    // 初始化控制器
    _controller = PageController();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('PageView - ZeroFlutter'),
      ),
      // 这里改为 PageView
      body: PageView(
        // 设置控制器
        controller: _controller,
        // 设置子项集
        children: children,
        // 添加页面滑动改变后,去改变索引变量刷新页面来更新底部导航
        onPageChanged: (value) {
          currentIndex = value;
          setState(() {});
        },
      ),
      // 底部导航栏
      bottomNavigationBar: [...],
    );
  }
}

子项页面内容

这里因为我们的页面内容肯定不是一成不变的,所以这篇我们将 PageDetails 继承自 StatefulWidget ,然后添加了 count 变量用于设置点击的次数。

/// 页面详情
class PageDetails extends StatefulWidget {
  PageDetails({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  _PageDetailsState createState() => _PageDetailsState();
}

class _PageDetailsState extends State<PageDetails> {
  int count = 0;
  @override
  Widget build(BuildContext context) {
    // 这里的打印可以记录一下,后面会用到
    print('PageDetails build title:${widget.title}');
    return Scaffold(
      body: GestureDetector(
        onTap: () {
          count += 1;
          setState(() {});
        },
        child: Center(
          child: Text('${widget.title} count:$count'),
        ),
      ),
    );
  }
}

底部导航

这里的底部导航当点击时,我们增加了一个控制器跳转页面的操作。

BottomNavigationBar(
  // 当前页面索引
  currentIndex: currentIndex,
  // 导航子项集
  items: [
    // 导航子项
    BottomNavigationBarItem(
      // 图标
      icon: Icon(Icons.home),
      // 文字内容
      label: '首页',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.message_rounded),
      label: '消息',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.people),
      label: '我的',
    ),
  ],
  onTap: (value) {
    // 点击事件,用于改变当前索引,然后刷新
    currentIndex = value;
    setState(() {});
    // 通过控制器实现跳转页面
    _controller.jumpToPage(currentIndex);
  },
)

运行效果

这样我们基础骨架就实现完毕,看下面的效果
03.gif

优化页面

细心的你会发现上图页面计数器在页面切换后又归零了,我们实际项目肯定是页面继续保持上次的状态,下面看看怎么优化吧。

这肯定是你在其他地方不会在介绍篇给你聊的内容,我新建的专栏 《Flutter Widgets》不光是简单介绍 Widget,各种实用技法、源码解析、Widget 关系链梳理都会有,记得看完点赞关注哦

保持页面状态

Flutter 早就为我们考虑好了这种情况,真正当我们遇到的时候才会去搜索学习。

/// 页面详情
class PageDetails extends StatefulWidget {
  PageDetails({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  _PageDetailsState createState() => _PageDetailsState();
}
/// 这里混入了 AutomaticKeepAliveClientMixin
class _PageDetailsState extends State<PageDetails>
    with AutomaticKeepAliveClientMixin {
  int count = 0;
  @override
  Widget build(BuildContext context) {
    super.build(context);
    // 这里的打印可以记录一下,后面会用到
    print('PageDetails build title:${widget.title}');
    return Scaffold(
      body: GestureDetector(
        onTap: () {
          count += 1;
          setState(() {});
        },
        child: Center(
          child: Text('${widget.title} count:$count'),
        ),
      ),
    );
  }
	// 设置 true 期望保持页面状态
  @override
  bool get wantKeepAlive => true;
}
  • 我们先看 9~11 行,with(混入)了一个 AutomaticKeepAliveClientMixinmixin
  • 31~32 行,覆写了 get wantKeepAlive 方法,返回 true 来保持页面状态

看看现在的效果

04.gif
到这里我们就实现带有切换效果的项目页面主骨架啦,如果觉得有帮助到你记得点击关注哦

源码仓库

基于 Flutter 🔥 最新版本

  • Flutter Widgets 仓库

参考链接

  • PageView (Flutter Widget of the Week)
  • Flutter-PageView

关注专栏

  • 此文章已收录到下面👇 的专栏,可以直接关注
  • 更多文章继续阅读|系列文章持续更新

👏 欢迎点赞➕收藏➕关注,有任何问题随时在下面👇评论,我会第一时间回复哦

深圳SEO优化公司崇左设计公司网站公司爱联SEO按天扣费哪家好三亚网站设计价格怀化网站推广方案价格重庆网站搭建推荐资阳百度竞价毕节网站seo优化报价德州优化公司哈密网站优化按天收费报价长沙设计公司网站公司淄博模板网站建设报价随州百搜标王推荐肇庆模板制作推荐迪庆网站推广推荐长春企业网站建设报价福田seo公司常州seo网站优化推荐眉山网络广告推广推荐普洱网站优化按天扣费大同seo排名多少钱玉树推广网站推荐松原网站优化按天扣费多少钱丹东网站设计公司丽江至尊标王哪家好普洱网站建设设计公司昆明百度标王黄山阿里店铺托管报价吉林模板推广多少钱桐城企业网站建设那曲关键词按天扣费报价歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化