前言
之前弄了不少flutter
的内容,这儿直接小小实战一下,就编写微信的 tabbar
上面的前四个页面来锻炼一下咱们的实战能力
—- 仿微信源码地址
别的看看效果(没细搞):
MaterialApp
跟其他大多数运用相同,咱们的开发都是从main
函数开端的,这儿咱们采用 MaterialApp
风格作为咱们根本组件(至少目前没用过其他组件),这儿面包含了咱们的 Router
导航等
void main() {
runApp(const App());
}
//由于没有涉及到状况的变更,一次运用 StatelessWidget 即可
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
//MaterialApp代表咱们主题纸墨风格框架,咱们一般开发都用这个
return MaterialApp(
//去掉debug自选
debugShowCheckedModeBanner: false,
//Android任务管理器界面title,能够设置称自己的app姓名
title: "Flutter Demo",
//设置我么你的色彩等
theme: ThemeData(
scaffoldBackgroundColor: Colors.white,
brightness: Brightness.light,
//设置一些card组件的布景色彩,例如一些弹窗组件的布景色彩
cardColor: const Color.fromRGBO(0x33, 0x33, 0x33, 0.8),
),
//这儿就是咱们的默许主页了
home: const HomePage()
);
}
}
Tabbar的HomePage
HomePage 是咱们编写的 Tabbar的一个界面,其操控谈天(chat)、联系人(contact)、发现(discover)、我的(mine),其他几个页面默许运用空组件占位即可,等待后续编写
别的,每开端一个新界面都需求运用Scaffold
组件进行包含,其包含着 appbar
和bottombar
的设置,以便于咱们后续开发(当然单纯封装的UI小组件不需求)
别的 Tabar
组件,咱们运用体系的 BottomNavigationBar
还远远不够,咱们运用了PageView
持有了其他四个页面的变量,而(在后边讲解为什么不是像ios
相同放了4个UI组件在一个数组)
然后经过 PageController
操控实践显现界面,此刻 BottomNavigationBar
单纯设置 bar
的UI效果,PageView
和 PageController
联动,则负责跳转功能
//编写时咱们承继自StatefulWidget,因为内部会更新状况
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
//初始化pagecontroller,用来操控page页面
final _controller = PageController(
initialPage: 0
);
//声明到这儿,能够默许保存,避免内次切换都要从头初始化,假如想从头初始化,能够特别处理
int _pageIndex = 0;
@override
Widget build(BuildContext context) {
//每开端一个新界面都需求运用Scaffold进行包含,其包含着 appbar和bottombar的设置
return Scaffold(
//这是一个 Widget 类型,能够自定义 tabbar,这儿运用体系的来测试
bottomNavigationBar: BottomNavigationBar(
//设置当时的index
currentIndex: _pageIndex,
//点击后能够用来 index 的选中效果,经过更新页面跳转
onTap: (int index) {
setState(() {
_pageIndex = index;
});
//除了更新bottombar图标,还要更新显现哪个页面
_controller.jumpToPage(index);
},
//设置了默许会显现字体,否则只有选中的才显现字体
unselectedItemColor: Colors.black,
selectedItemColor: Colors.green,
//设置为混合类型,默许未选中只显现一个icon图片
type: BottomNavigationBarType.fixed,
selectedFontSize: 12,
unselectedFontSize: 12,
//设置里面组件
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
label: "谈天",
icon: Image.asset('images/tabbar_chat.png',
width: 20,
height: 20
),
activeIcon: Image.asset('images/tabbar_chat_hl.png',
width: 20,
height: 20
)
),
BottomNavigationBarItem(
label: "联系人",
icon: Image.asset('images/tabbar_contact.png',
width: 20,
height: 20
),
activeIcon: Image.asset('images/tabbar_contact_hl.png',
width: 20,
height: 20
)
),
BottomNavigationBarItem(
label: "发现",
icon: Image.asset('images/tabbar_discover.png',
width: 20,
height: 20
),
activeIcon: Image.asset('images/tabbar_discover_hl.png',
width: 20,
height: 20
)
),
BottomNavigationBarItem(
label: "我的",
icon: Image.asset('images/tabbar_mine.png',
width: 20,
height: 20
),
activeIcon: Image.asset('images/tabbar_mine_hl.png',
width: 20,
height: 20
)
)
],
),
body: PageView(
controller: _controller,
//不设置默许能够左右活动,假如不想左右滑动如下设置,能够依据ios或者android来设置
// physics: const NeverScrollableScrollPhysics(),
//界面切换后的回调,主要是针对android左右滑动回调,此刻与bottombar无关了
onPageChanged: (int index) {
setState(() {
_pageIndex = index;
});
},
//设置咱们要切换的页面,放到一个数组
children: const [
ChatList(),
Contact(),
Discover(),
Mine()
],
),
);
}
}
tabbar的问题点
过错示范
看了相面估量有疑问,我试了一下,将四个页面放到一个数组中,然后直接依据index
切换body
的实践页面也能够呀,如下所示,我第一次也这么写的(这儿是过错示范
)
//过错示范,但看起来效果也是相同
final List _pageList = [ChatList(), Contact(), Discover(), Mine()];
body: _pageList[_pageIndex]
问题
问题一
咱们声明的组件默许在build
中有一个根本组件的声明,这是咱们声明的组件,咱们正常能够经过变量来操控某个界面的显现和躲藏
,于此一起也操控着一些组件的创立和销毁
因而,当咱们的组件挂载到 body
中时,也就意味着每次都切换组件,那么被切换的组件就会开释,而咱们 _pageList
寄存的仅仅没有状况未烘托的widget小组件
,跟咱们直接放一个Text相同,每一次切换会从头创立当时组件和烘托,而且强制开释上一个组件的内容,因而其状况无法保存
问题二
然后可能会尝试,发现运用了 PageView
,为什么 initState
和 build
也会重走呢,这就涉及到了 flutter
的烘托机制,其默许只会烘托当时一屏的内容,且不会保存组件的默许状况,一旦切换其他页面,需求从头初始状况,但有一点该组件并没有开释,咱们的组件一直在 PageView
中持有,因而没有开释
体系给咱们提供了一个 maxin
类 AutomaticKeepAliveClientMixin
,咱们能够采用多承继的方法,承继自它,那么这个状况就会被保存,就不需求从头烘托后
例如: chat
组件,当咱们多承继(with
它) AutomaticKeepAliveClientMixin
,需求重写他的 wantKeepAlive
属性,设置为 true
,然后在 build
中 调用一下 super.build
即可
后边章节都会有代码实例,介绍 AutomaticKeepAliveClientMixin
的运用
pubpec.yaml
这个文件包含了咱们的的 sdk版别号、三方仓库、图片资源名称等
//平常用不到,当迁移文件或者改名,记得改一下
name: flutter_wechat_demo
description: 一个仿微信的实战测试demo
//环境sdk版别,一般默许的即可,假如几台电脑不相同,能够依据状况设置最低版别
environment:
sdk: ">=2.16.1"
//三方依靠,一般运用 flutter pub get + 三方库 方法导入
//在这儿导入,需求点击右上角 Pub get更新
dependencies:
flutter:
sdk: flutter
http: ^0.13.4
//测试版别依靠
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^1.0.0
//图片资源库地址,图片仓库姓名一般与咱们ios、android仓库同级
//放入图片后,只需求右键复制路径,粘到这儿即可
flutter:
uses-material-design: true
assets:
- images/tabbar_chat.png
- images/tabbar_chat_hl.png
- images/tabbar_contact.png