往期
上期回顾
上期主要完成环境的搭建和部署,最终在jetpack.net.cn地址上呈现,这期我们就开始搭建主页,构建一个可以兼容三端(Android、Ios、Web)的主页。
开始
在lib文件夹下创建home.dart文件,如图







ScreenUtil.instance = ScreenUtil.getInstance()..init(context);
而且初始化必须在MaterialApp包裹中,为什么呢?因为我们使用了MediaQuery动态获取屏幕的宽高,详细请看官方文档api.flutter.dev/flutter/wid…里面讲的很清楚: WidgetsApp and MaterialApp, which introduce a MediaQuery and keep it up to date with the current screen metrics as they change. 目前WidgetsApp和MaterialApp实现了MediaQuery的逻辑,所以你不在MaterialApp中初始化是会报错地,知道了吧。接下来看下实际运行效果,我们将内容设置成红色来看,如图



responsive_builder: ^0.1.5
我为什么没有选择直接使用呢?其实我们在明白其中原理后确实可以直接引用,但我还是建议自己写一遍,通过自己的实现,更清楚其中的道理不是吗。前期的学习过程中,我们尽量的不去引用,选择自己实现,也是加快提高自己的一个办法。多多学习,多多练习。接下来我们实现Scaffold部分,Scaffold这个组件太好用了,先看下它原本的样子



@override
Widget build(BuildContext context) {
ScreenUtil.instance = ScreenUtil.getInstance()..init(context);
return Material(
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: !ResponsiveWidget.isSmallScreen(context)
? (ScreenUtil.getInstance().setWidth(108))
: (ScreenUtil.getInstance().setWidth(6))),
child: Scaffold(
appBar: AppBar(
title: _buildTitle(), /// 左边标题
backgroundColor: Color(0xFFf1f3f4),
actions: !ResponsiveWidget.isSmallScreen(context)
? _buildActions(context)
: null, /// 右边的menu菜单,这里在小屏幕不显示。
),
body: Center(child: Text('You have pressed the button $_count times.')),
),
));
}
Widget _buildTitle() {
return RichText(
text: TextSpan(
// Note: Styles for TextSpans must be explicitly defined.
// Child text spans will inherit styles from parent
style: TextStyle(
fontSize: 14.0,
color: Colors.black,
),
children: <TextSpan>[
TextSpan(
text: "Jetpack",
style: TextStyles.logo,
),
TextSpan(
text: ".net.cn",
style: TextStyles.logo.copyWith(
color: Color(0xFF50AFC0),
),
),
],
),
);
}
_buildActions(BuildContext context) {
return <Widget>[
MaterialButton(
child: Text(
'Home',
style: TextStyles.menuItem,
),
onPressed: () {
if (ResponsiveWidget.isSmallScreen(context)) Navigator.pop(context);
},
),
MaterialButton(
child: Text(
'About',
style: TextStyles.menuItem,
),
onPressed: () {
if (ResponsiveWidget.isSmallScreen(context)) Navigator.pop(context);
},
),
];
}
分别通过_buildTitle,_buildActions 实现左边的标题,右边的菜单按钮,里面有个细节:

///省略部分代码
Scaffold(
///省略部分代码
drawer: _buildDrawer(context),
),
_buildDrawer(BuildContext context) {
return ResponsiveWidget.isSmallScreen(context)
? Drawer(
child: ListView(
padding: const EdgeInsets.all(20),
children: _buildActions(context),
),
)
: null;
}
给Scaffold添加一个drawer组件,这里用ListView把刚才的_buildActions组件再放进来,原来是以横向展示,这次因为ListView默认是纵向,所以就是上下的展示方式,运行项目后,如图:









int _selectedDrawerIndex = 0;
///定义一个坐标值
/// 添加动态的body _getDrawerItemWidget
child: Scaffold(
body: _getDrawerItemWidget(_selectedDrawerIndex),
),
/// 省略部分代码
/// 根据一个index值,来确定加载哪个页面
_getDrawerItemWidget(int selectedDrawerIndex) {
switch(selectedDrawerIndex){
case 0:
return WidgetMenuHome();
break;
case 1:
return WidgetMenuAbout();
break;
}
}
/// 在_buildActions函数中的组件onPressed的时候调用,这样就可以更新UI
setState(() {
_selectedDrawerIndex = 0;
});
好了这期我们就先这样,学习到此结束,下期继续。
总结
这次主要是对Scaffold的使用,以及如何构建不同平台的UI,确切说是不同宽度屏幕的构建,实现了大屏幕的Menu菜单,和小屏幕的Drawer菜单显示,而且没有考虑分包,下期将进行分包设计,并往页面里面填充内容,来构建我们的需求UI 实现一个Flutter Jetpack,并把之前做的Android Jetpack也挪过来。
项目开源链接
Android Jetpack WebSite Flutter Jetpack WebSite Flutter Jetpack Github Source Code Android Jetpack Github Source Code