在这个系列中,咱们将学习如何使用google的移动开发框架flutter建立一个电商应用。 本文是flutter框架系列教程的第一部分,将学习如何安装Flutter开发环境并建立第一个 Flutter应用,并学习Flutter应用开发中的核心概念,例如widget、状态等。android
本系列教程包含以下四个部分,敬请期待:git
Flutter的开发文档至关出色,请参考官方文档先安装开发环境。github
一旦开发环境安装好,咱们能够建立一个新的测试项目。我倾向于使用android studio,由于它为flutter应用的开发 提供了一个完备的集成开发环境。你须要在Android studio中安装一个Dard语言插件。app
如今启动Android Studio,你会看到初始化Flutter项目的选项:框架
从配置列表中选择**Flutter Application **。less
能够为你的第一个Flutter应用起一个酷炫的名字,不过若是你和我同样不善于起名,就用timer好了。异步
对话框的最后一步,会要求咱们填写应用的包名:ide
接下来Flutter SDK就会为应用建立一个初始的目录结构,main.dart是应用执行的入口。布局
在Flutter中,一切都是控件(widget)。Flutter应用中的图像、图标和文本都是widget。布局元素 例如行、列、栅格等用来安排其余widget的位置、大小和对齐,而这些布局元素自己也是widget。学习
参考以下代码修改你的main.dart文件:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Welcome to Flutter', home: Scaffold( appBar: AppBar( title: Text('Welcome to Flutter'), ), body: Center( child: Text('Hello World'), ), ), ); } }
如今启动Android模拟器:
注意widget的焦点,咱们接下来将修改MaterialApp的内容。先看一下原始版本:
body: Center( child: Text('Hello World'), )
Flutter中的布局元素(也是widget)能够根据其是否支持包含多个widget,而简单地归类为两种类型。 例如,Container、Padding只能包含一个子widget,而Row、Column则能够包含多个。
如今咱们在Row布局中引入三个文本widget:
body: Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text('0'), Text('0'), Text('0'), ], ), ),
如今看起来是这样:
在咱们开始设置组件的样式以前,建议先建立一个新的widget来处理样式问题,以便遵循DRY(Don't Repeat Yoursel)原则。
将三个子widget用一个自定义widget(后面解释)替换。如今main.dart文件变成:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Welcome to Flutter', home: Scaffold( appBar: AppBar( title: Text('Timer'), ), body: Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ CustomTextContainer(), CustomTextContainer(), CustomTextContainer(), ], ), ), ), ); } } class CustomTextContainer extends StatelessWidget { @override Widget build(BuildContext context) { return Text('00'); } }
我不是很擅长用户界面,可是咱们仍是尽力吧,加点背景色,留点空白:
class CustomTextContainer extends StatelessWidget { CustomTextContainer({this.label, this.value}); final String label; final String value; @override Widget build(BuildContext context) { return Container( margin: EdgeInsets.symmetric(horizontal: 5), padding: EdgeInsets.all(20), decoration: new BoxDecoration( borderRadius: new BorderRadius.circular(10), color: Colors.black87, ), child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ Text( '$value', style: TextStyle( color: Colors.white, fontSize: 54, fontWeight: FontWeight.bold, ), ), Text( '$label', style: TextStyle( color: Colors.white70, ), ) ], ), ); } }
同时,在文本下面插入一个按钮widget,修改后的代码运行结果以下:
如今到了app最不可或缺的部分了:状态。状态将持有timer的当前值和运行标识。我 补充了一个TimerState类,它负责维护状态,同时构建widget树。
class Timer extends StatefulWidget { @override State<StatefulWidget> createState() { return new TimerState(); } } class TimerState extends State<Timer> { int secondsPassed = 0; bool isActive = false; @override Widget build(BuildContext context) { // Return Widget Tree } }
按钮用来切换timer的运行或者中止:
RaisedButton( child: Text(isActive ? 'STOP' : 'START'), onPressed: () { setState(() { isActive = !isActive; }); }, )
Dart有个用于异步操做的优雅的模块。咱们可使用其Timer类来实现读秒。修改后的 TimerAppState代码以下,注意咱们已经重构Timer类并更名为TimerApp以免与异步 模块中的Timer类混淆:
class TimerAppState extends State<TimerApp> { static const duration = const Duration(seconds:1); int secondsPassed = 0; bool isActive = false; Timer timer; void handleTick() { if (isActive) { setState(() { secondsPassed = secondsPassed + 1; }); } } @override Widget build(BuildContext context) { if (timer == null) timer = Timer.periodic(duration, (Timer t) { handleTick(); }); int seconds = secondsPassed % 60; int minutes = secondsPassed ~/ 60; int hours = secondsPassed ~/ (60*60); return MaterialApp(...) } }
好了,咱们已经完成了第一个Flutter应用,完整的Dard代码能够在这里下载。