前言
从这里开始,我就准备边学边做边用博客记录下自己的重构历程,会结合已有的app的样式进行重构。
原图
先看一下app的截图:
上面两个截图是app的首页和左侧菜单栏的截图,首页下方是一个可以滑动的tab+viewpager,左侧菜单栏是一个drawerlayout。
目标图像
这是实现的效果图
接下来将会逐一分析界面并给出代码。
解析
首先我们要做的就是划分好界面层次,这一步操作还是很简单的,我直接贴出来目前的页面层次结构
在flutter中,一切都是widget,也就是说所见的都是控件,一个空间就是一个类,一个类可以放在一个dart文件里面,也就是说可以理解为一个控件就是一个dart文件。在这里项目目录分级为如下几个部分:
assets文件夹存放相关的资源文件
lib文件为存放dart文件的地方
common文件夹用于存放app执行所需要的文件
pages文件夹用于存放页面文件
pages/main存放的是首页的页面文件
pages/school存放的是校园部分的页面文件
app.dart是首页的页面文件
main.dart是整个app的入口文件
入口文件
入口文件很简单,直接上代码
import 'package:flutter/material.dart';
import 'package:flutter_guohe/pages/main.dart';
void main() {
runApp(new Guohe());
}
底部tabbar的实现
从之前的层次图就可以看出,tabbar控制着3个页面,所以他应该是首页的顶级元素,在app.dart中添加如下代码,具体参考《Flutter底部导航栏的实现》
/**
* APP的主入口文件
*/
import 'package:flutter/material.dart';
import 'package:flutter_guohe/pages/main/today.dart';
import 'package:flutter_guohe/pages/main/playground.dart';
import 'package:flutter_guohe/pages/main/kb.dart';
import 'package:flutter_guohe/pages/main/leftmenu.dart';
import 'package:flutter_guohe/common/eventBus.dart';
//果核的主界面
class Guohe extends StatefulWidget {
@override
GuoheState createState() => new GuoheState();
}
class GuoheState extends State<Guohe> with SingleTickerProviderStateMixin {
TabController controller;
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override
void initState() {
controller = new TabController(length: 3, vsync: this);
eventBus.on<EventOpenDrawer>().listen((EventOpenDrawer data) {
if (data.flag) _scaffoldKey.currentState.openDrawer();
});
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
key: _scaffoldKey,
drawer: new LeftMenu(),
body: new TabBarView(
controller: controller,
children: <Widget>[
new Today(),
new Kb(),
new Playground(),
],
),
bottomNavigationBar: new Material(
color: Colors.white,
child: new TabBar(
controller: controller,
labelColor: Colors.deepPurpleAccent,
unselectedLabelColor: Colors.black26,
tabs: <Widget>[
new Tab(
text: "今日",
icon: new Icon(Icons.brightness_5),
),
new Tab(
text: "课表",
icon: new Icon(Icons.map),
),
new Tab(
text: "操场",
icon: new Icon(Icons.directions_run),
),
],
),
),
),
);
}
}
左侧菜单栏
左侧菜单栏就是一个drawer,就是一个抽屉,在Scaffold中申明就好了,在这里我为了看起来不那么乱,创建了一个leftmenu.dart文件用来展示左侧菜单界面,只要知道了row、column、padding的用法就可以很快的写出来了,参考《flutter实战1:完成一个有侧边栏的主界面》。下面贴代码
import 'package:flutter/material.dart';
//左侧菜单栏
class LeftMenu extends Drawer {
@override
Widget build(BuildContext context) {
return new Drawer(
//侧边栏按钮Drawer
child: new ListView(
children: <Widget>[
//个人信息部分
new Container(
color: Color.fromARGB(255, 119, 136, 213),
child: new Padding(
padding: new EdgeInsets.all(26.0),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Row(
children: <Widget>[
//头像
new Container(
width: 80.0,
height: 80.0,
margin:
new EdgeInsets.only(right: 10.0, bottom: 15.0),
decoration: BoxDecoration(
image: DecorationImage(
image: new NetworkImage(
'http://www.chedan5.com/upload/article/201803/06/1740235a9e62077e0aexbcUQh.jpg'),
//从Assets加载图片
fit: BoxFit.cover,
),
shape: BoxShape.circle,
),
),
new Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text(
'梁越勇',
style: new TextStyle(
color: Colors.white, fontSize: 25.0),
),
new Text(
'152210702112',
style: new TextStyle(
color: Colors.white, fontSize: 15.0),
)
],
)
],
),
new Text(
"计算机学院",
style: new TextStyle(color: Colors.white, fontSize: 18.0),
)
],
),
)),
new ListTile(
//第二个功能项
title: new Text('关于我们'),
leading: new Icon(Icons.accessibility),
onTap: () {
Navigator.of(context).pop();
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text("关于我们"),
));
}),
//分割线控件
new ListTile(
//退出按钮
title: new Text('分享此应用'),
leading: new Icon(Icons.share),
onTap: () {
Navigator.of(context).pop();
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text("分享此应用"),
));
} //点击后收起侧边栏
),
//分割线控件
new ListTile(
//退出按钮
title: new Text('给我们反馈'),
leading: new Icon(Icons.feedback),
onTap: () {
Navigator.of(context).pop();
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text("给我们反馈"),
));
} //点击后收起侧边栏
),
//分割线控件
new ListTile(
//退出按钮
title: new Text('联系开发者'),
leading: new Icon(Icons.flight),
onTap: () {
Navigator.of(context).pop();
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text("联系开发者"),
));
} //点击后收起侧边栏
),
//分割线控件
new ListTile(
//退出按钮
title: new Text('加入交流群'),
leading: new Icon(Icons.group_add),
onTap: () {
Navigator.of(context).pop();
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text("加入交流群"),
));
} //点击后收起侧边栏
),
new ListTile(
//退出按钮
title: new Text('切换账号'),
leading: new Icon(Icons.sync),
onTap: () {
Navigator.of(context).pop();
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text("切换账号"),
));
} //点击后收起侧边栏
),
new ListTile(
//退出按钮
title: new Text('检测升级'),
leading: new Icon(Icons.refresh),
onTap: () {
Navigator.of(context).pop();
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text("检测升级"),
));
} //点击后收起侧边栏
),
new ListTile(
//退出按钮
title: new Text('更新说明'),
leading: new Icon(Icons.info),
onTap: () {
Navigator.of(context).pop();
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text("更新说明"),
));
} //点击后收起侧边栏
),
],
),
);
}
}