Flutter 中 IndexedStack 的使用详解 _ Flutter Widgets

index:0index:1index:2
image.pngimage.pngimage.png

上面我们调整不同的 index 只显示出来了一个子项 Widget,如果我们把 IndexedStack 换成 Stack 则会显示成如下效果。
image.png

IndexedStack 源码

  • alignment 对齐方式
  • sizing 填充方式
  • index 显示子项索引
  • children 子项集合

本篇主要聊 indexchildren ,其他的 alignment、sizing 可以稍后转看专栏中 Stack 详解篇,我们开始看看源码吧!
image.png
我们可以看到 IndexedStack 其实就是 Stack 的子类,对齐方式和填充方式都是直接传递到父类的,所以我们这篇只关心 index 即可。

效果实现

主体内容

我们先开始主体部分的布局,这里使用 IndexedStack ,添加一个 currentIndex 来记录当前子项索引,当我们改变 currentIndex 值后刷新即可实现切换页面效果啦。

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

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

class _IndexedStackPageState extends State {
// 当前子项索引
int currentIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(‘IndexedStack - ZeroFlutter’),
),
body: IndexedStack(
alignment: Alignment.center,
// 设置当前索引
index: currentIndex,
children: [
PageDetails(title: ‘首页’),
PageDetails(title: ‘消息’),
PageDetails(title: ‘我的’),
],
),
bottomNavigationBar: [下面聊到],
);
}
}

子项内容

这里我们简单使用一个 StatelessWidget 然后再脚手架中添加一个居中的 Text 用来显示一个页面 title

这里的 print 方法也先记录一下,下面会用到。

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

@override
Widget build(BuildContext context) {
// 这里的打印可以记录一下,后面会用到
print(‘PageDetails build title:$title’);
return Scaffold(
body: Center(
child: Text(title),
),
);
}
}

底部导航

我们使用 BottomNavigationBar 做个简单的底部切换的导航,之后会详细聊聊这个 Widget,记得关注我得专栏《Flutter Widgets》不光是简单介绍Widget,各种实用技法、源码解析、Widget 关系链梳理都会有。

Scaffold(
appBar:[…],
body: IndexedStack(),
// 底部导航栏
bottomNavigationBar: BottomNavigationBar(
// 当前索引和 IndexedStack 使用同一个变量
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(() {});
},
),
)

效果展示

这样我们就实现了展示的效果

精进优化

还记得我们上面在子项详情页打印的内容吗?再看一遍他

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

@override
Widget build(BuildContext context) {
// 这里的打印可以记录一下,后面会用到
print(‘PageDetails build title:$title’);
return Scaffold(
body: Center(
child: Text(title),
),
);
}
}

现在当我们切换导航的时候,看看控制台的打印是什么?
image.png
首次进来打印了 1 次,之后切换了 2 次又分别打印了 2 次。我们这里做了一个简单的主页,实际项目中这4个页面承担了很多,也是用户接触最多的页面,要是切换就 build 一次这谁顶得住,我们必须优化。

如何优化?

分析原因

这里我们为了简单 PageDetails 是继承自 StatelessWidget 的,那么 StatelessWidget 发生 build 无外乎以下 3 种情况(源码注释中有写到)

  • 1、第一次插入到树🌲中
  • 2、Widget 父类改变了配置
  • 3、依赖 InheritedWidget 改变了他

那么到底是谁改变了他呢?我们来一起分析一下。

  • 第 1 项没有什么疑问
  • 第 3 项我们没有依赖于 InheritedWidget
  • 那就只有第 2 项了

还记得记录当前索引的变量 currentIndexBottomNavigationBaronTap 方法吗?

BottomNavigationBar(
// 当前索引和 IndexedStack 使用同一个变量
currentIndex: currentIndex,
onTap: (value) {
// 点击事件,用于改变当前索引,然后刷新
currentIndex = value;
setState(() {});
},
)

在回到现象,当我们切换的时候会重新build,这里我们只有这里改变了 currentIndex 的值并且调用了 setState 刷新,然后父类(IndexedStackPage)重新 build 了,所以子项的详情页面也会跟着 build

调整优化

我们现在分析出了原因,那么接下来怎么去优化代码呢?我这里提供 2 种方式

  • 添加 const 关键字修饰 PageDetails
  • 将子项集初始化放到 initState 当中

IndexedStack(
alignment: Alignment.center,
index: currentIndex,
children: [
// 这里添加 const 关键字修饰
const PageDetails(title: ‘首页’),
const PageDetails(title: ‘消息’),
const PageDetails(title: ‘我的’),
],
)

// 当前子项索引
int currentIndex = 0;

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门**

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值