Flutter入门:教程1 基础
在本教程中,我将一步一步地指导您构建您的第一个 Flutter 应用。
引言
您好! 这就是我的架构师在每次开始每日站会时说的话。我时隔许久再次写文章,也是同样的开场白。这是我的一个缺点,因为我很久没有学到任何新东西或值得分享的东西了!这些年来,我一直厚颜无耻地从别人那里获取灵感,而贡献甚少。
我上次写文章是在 Xamarin
(那时它们还是独立软件,未被微软收购)的时候,那时 Joseph Hill 先生慷慨地分享了一个免费许可证给我。虽然我用它编码了一段时间后,由于我主要专注于 Android 平台,我觉得 C# 的代码编写很麻烦,因为它在内部将代码编译成 Java,并且代码结构与 Java 类似(例如事件处理程序等),我从未感到自在。渐渐地,我失去了兴趣,彻底放弃了移动平台学习。
然而,最近我发现了一个由 Google 开发的非常棒的跨平台移动开发工具,那就是 Flutter,尽管它仍处于 Beta 阶段,但我相信它有着光明的未来。此外,开发语言是 Dart,我很庆幸它比其他语言更接近 C++/C#,更容易学习,而且它是开源且积极开发的。尽管 Xamarin 移动开发套件现在可以通过 VS2017 社区版 免费获得。
背景
我引用自这篇 链接,作者是 Wm Leler 先生:
引用“Flutter 是唯一一个无需 JavaScript 桥即可提供响应式视图的移动 SDK,这一点本身就足以让 Flutter 引起兴趣并值得尝试,但 Flutter 还有更具革命性的东西,那就是它实现 Widget 的方式。”
这张图片摘自上面同一个链接,它会让你了解 Flutter 如何原生渲染应用程序。
为什么 Flutter 使用 Dart
为了避免重复,我将引用这篇 链接 的内容,作者是 Wm Leler 先生。
- Dart 可以 AOT(Ahead Of Time,提前编译)为快速、可预测的原生代码,这使得几乎所有 Flutter 的内容都可以用 Dart 编写。这不仅使 Flutter 快速,而且几乎所有东西(包括所有 Widget)都可以进行自定义。
- Dart 还可以 JIT(Just In Time,即时编译)以实现极快的开发周期和颠覆性的工作流程(包括 Flutter 流行的亚秒级有状态热重载)。
- Dart 可以更容易地创建流畅的动画和过渡,以 60fps 运行。Dart 可以在没有锁的情况下进行对象分配和垃圾回收。并且像 JavaScript 一样,Dart 避免了抢占式调度和共享内存(因此也避免了锁)。由于 Flutter 应用被编译为原生代码,因此它们不需要在不同领域之间进行缓慢的桥接(例如 JavaScript 到原生)。它们的启动速度也快得多。
- Dart 使 Flutter 能够避免需要像 JSX 或 XML 这样的单独的声明式布局语言,或单独的视觉界面构建器,因为 Dart 的声明式、编程性布局易于阅读和可视化。由于所有布局都用一种语言在一个地方完成,因此 Flutter 可以轻松地提供使其布局变得轻而易举的高级工具。
- 开发者发现 Dart 特别容易学习,因为它具有静态语言和动态语言用户都熟悉的特性。
总之,让我们开始吧。我将尽快发布单独的教程来介绍 Dart 语言的技巧和窍门, 我已经发布了本系列的第一篇文章,请 点击这里 访问第一篇。构建这些教程所需的工具如下:
- Flutter - https://flutter.io/setup-windows/
- Android Studio - https://developer.android.com.cn/studio/
虽然您可以使用 Visual Studio Code 代替 Android Studio,但我建议安装 Android Studio,因为它现在包含可视化 Android SDK。从命令行安装 SDK 会比较困难。至少,对于初学者来说,绝对不行。
Using the Code
我将在本教程中执行以下操作,我将只专注于 StatelessWidget
。
- 任务#1:创建一个带有显示标题的
AppBar
的页面。 - 任务#2:在页面中间放置一个 Raised Button,并在
onClick
时显示 Snackbar。 - 任务#3:在底部栏放置带有图标的按钮,并响应点击。
一如既往,就像我的其他文章一样,我假设阅读本文的人是新手,我会一步一步地开始。
- 打开 Android Studio,像这样配置 Flutter 和 Dart SDK/插件。您需要点击 File->Settings 并选择 plugins 来打开此页面。
如果您没有看到已安装的插件,请按 Browse repositories 按钮并搜索 Flutter 插件,它也会一并安装 Dart 插件。
- 现在创建一个新的 Flutter 项目,并将其命名为 '
tutorial1
',请注意项目名称始终是小写。按 next 设置包名,然后最终完成。 - 删除项目创建时生成的所有样板代码。您的 lib 文件夹下的 main.dart 文件应该看起来像这样:
import 'package:flutter/material.dart'; import 'package:tutorial1/myhomepage.dart'; void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return new MaterialApp( title: 'Flutter Demo', theme: new ThemeData( primarySwatch: Colors.blue, ), home: new MyHomePage(title: 'Flutter Tutorial #1'), ); } }
我来解释一下这段代码的含义。- Flutter/Dart 项目的入口点是
main
(),所以我们使用简短的代码 forRunApp
,并传递MyApp
的对象。MyApp
作为我们教程的基础类,您可以随意命名,只要它符合Dart
类声明格式。 MyApp
类继承自StatelessWidget
(一个不需要可变状态的 Widget)。- 我们将重写 build 方法并返回
MaterialApp
。在 home 属性中,我提供了一个MyHomePage
对象,它将作为页面显示的主类。 - Flutter 使用 Material Design,以在跨平台提供相似的外观。
MyHomePage
。我们将在下一步创建它。 - Flutter/Dart 项目的入口点是
- 右键单击 lib 文件夹,然后悬停在 new item 上,以创建新的 Dart 文件。将其命名为 myhomepage.dart。您只需键入文件名,它会自动添加后缀。
- 将以下代码添加到 myhomepage.dart 文件中:
import 'package:flutter/material.dart'; class MyHomePage extends StatelessWidget{ final String title; MyHomePage({this.title}) { } @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text(title,style: new TextStyle(fontSize: 15.0),), ), ); } }
- 在这里,我们创建了
MyHomePage
类,它继承自StatelessWidget
。 - 创建一个构造函数,并在参数中使用
{this.title}
,为final
title 变量提供命名参数和值。const
和final
之间的关键区别在于,const
需要在编译时定义,而final
变量可以在第一次初始化时定义。 - 我们需要重写
Widget build(BuildContext context)
方法,并返回一个Scaffold
对象,其中包含AppBar
的信息。 - 在这里,
appBar
是Scaffold
类的属性,需要用AppBar
对象进行初始化,您可以在其中指定要显示的标题。
- 在这里,我们创建了
- 第一次运行,键入 Shift+F10 或按 播放 按钮来运行您的项目。请确保您的模拟器正在运行,以便看到您的应用程序。
顶部右侧的 Debug 标记表示我们正在 Debug 模式下运行此应用程序。至此,我们完成了任务#1。
- 现在是任务#2。由于 Flutter 中的一切都是 Widget,我们将创建一个新的类
MySnackBarClass
,并将其对象提供给MyHomePage
中Scaffold
的 body 属性。因此,MyHomePage
的 build 方法将如下所示:Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text(title,style: new TextStyle(fontSize: 15.0),), ) , body: new MySnackBarClass() ); }
新增部分以粗体标出。 - 现在创建
MySnackBarClass
类,并提供以下代码:class MySnackBarClass extends StatelessWidget{ @override Widget build(BuildContext context) { return new Container( child: new Center( child: new Column( mainAxisAlignment: MainAxisAlignment.center, children: <widget>[ new RaisedButton( onPressed: (){ final mySnackBar = new SnackBar( content: Text('Hello from SnackBar'), //text to display duration: Duration(seconds: 10), // Duration to display ); Scaffold.of(context).showSnackBar(mySnackBar); }, child: new Text("Click Me"), color: Colors.amber, ), ], ) ), ); } } </widget>
代码解释
- 在这里,我们返回一个
Container
对象,它将充当放置各种 UI 元素的容器。 - 我们希望内容居中对齐页面,因此我们使用了
Center
Widget,并将其 child 对象设置为Columns
,将其主轴对齐设置为center
。 - 由于我们可以在 Column Widget 中放置多个 Widget,因此它有一个 children 属性而不是 child 属性,它接受 Widget 数组。
- 在这里,我们提供了
RaisedButton
对象,其颜色为amber
,标签为 Click Me,onPressed
是一个匿名函数,用于显示SnackBar
。 - 我们创建了一个带有文本和可见持续时间的
Snackbar
对象。 - 最后,我们使用
Scaffold.of()
方法来显示SnackBar
。
- 在这里,我们返回一个
- 使用 Hot reload 来刷新模拟器。如果不起作用,您可以执行 hot restart。
所以任务#2在这里完成。
- 为了添加底部导航栏,我们需要利用
Scaffold
类的bottomNavigationBar
属性。我们将采用与任务#2相同的方法,创建一个单独的类来处理底部导航栏。更改后,MyHomePage
中 build 方法的代码将如下所示:Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text(title,style: new TextStyle(fontSize: 15.0),), ) , body: new MySnackBarClass(), bottomNavigationBar: new MyBottomNavigationBar(), ); }
在这里,我们将创建
MyBottomNavigationBar
类来为底部栏提供 UI 元素。 - 创建
MyBottomNavigationBar
类,以下是代码示例:class MyBottomNavigationBar extends StatelessWidget{ @override Widget build(BuildContext context) { return new ButtonBar( alignment: MainAxisAlignment.center, children: <widget>[ new IconButton(icon:new Icon(Icons.airline_seat_recline_normal), onPressed: (){ print('hello'); }) ], ); } }
这是对以上代码的解释:- 我们正在返回一个
ButtonBar
对象,它提供了在其 Widget 树中放置多个 Widget 的能力。 - 将
ButtonBar
的对齐方式设置为 center,以居中显示内容。 - 创建一个带有
airline_seat_recline_normal
图标类型的IconButton
。
- 我们正在返回一个
- 最后一次 Hot reload 来查看您的更改。
至此,本教程结束,敬请期待更多内容。您也可以在 GitHub 上查看源代码 https://github.com/thatsalok/FlutterExample/tree/master/tutorial1。
关注点
请阅读以下文章。它们可能会让你大致了解当前的风向。
Flutter 教程
Dart 教程
历史
- 2018 年 7 月 5 日:初版
- 2018 年 7 月 11 日:更新了其他教程引用。
- 2018 年 7 月 14 日:更新了其他教程引用,进行了一般性文章修复。