前面三篇可以算是一个小小的里程碑。

主要是介绍了 Flutter 环境的搭建、如何创建 Flutter 项目以及如何在旧有 Android 项目引入 Flutter。

这一篇我们来学习下 Flutter 的 UI。

前言

说到 UI,我就简单说下 Flutter 作为一门跨平台语言具有的优势之一,提高效率吧。

举个例子:

假设现在要开发一个界面,Android 开发需要一天,iOS 开发也需要一天。那么就是两天。

如果你用 Flutter 开发,就只需要一天(因为 Android 和 iOS 都可以共用一套 Flutter 代码)。这样效率自然就提高了。

另外,假设后面产品发现界面有个位置需要调整,如果是 Android 或者 iOS 单独开发,则两个端都需要进行额外调整。

而 Flutter 就一套代码而已,所以相较之下 Flutter 更易维护。

官网关于 UI 的介绍 User interface

这边笔者按照自己的感受和认识进行说明。

读者看完之后有了个基本的认识,后续不管是阅读官方文档还是使用搜索引擎搜索相关问题,相信会事半功倍。

记住一句话:

Flutter 里面一切皆 Widget。

目录

1. 基本配置

我们紧接之前文章,现在进入 MyApp/sub/my_flutter 位置。

打开 main.dart。如果提示下图:

Dart support is not enabled for the project

我们点击右边第一个(Enabled Dart support)或者第二个(Open Dart settings)都是 OK 的。

如果点击第二个,需要配置 dart 的目录。

dart 的目录在 flutter 的 bin 目录下面的 cache 目录下面。

举个例子,笔者的 flutter bin 目录(terminal 执行which flutter)为/Users/nesger/Desktop/nesger_folder/flutter/flutter/bin/,那么 dart 目录就在/Users/nesger/Desktop/nesger_folder/flutter/flutter/bin/cache/dart-sdk

然后直接拷贝下面代码替换 main.dart 的代码。

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(MyApp());
  3. class MyApp extends StatelessWidget {
  4. @override
  5. Widget build(BuildContext context) {
  6. return MaterialApp(
  7. home: Scaffold(
  8. appBar: AppBar(
  9. title: Text('My Flutter'),
  10. ),
  11. body: Center(),
  12. )
  13. );
  14. }
  15. }

实际编译器可能会显示如下图,就是会有注释显示每个控件。

这有好处也有坏处。好处就是你可以看到哪一块是哪一个 Widget。坏处就是视觉干扰。

这个是自动产生的,不可删除。

可以通过如下操作控制是否显示:

Android Studio->Preferences->Editor->General->Appearance

2. main.dart 学习

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(MyApp());
  3. class MyApp extends StatelessWidget {
  4. @override
  5. Widget build(BuildContext context) {
  6. return MaterialApp(
  7. home: Scaffold(
  8. appBar: AppBar(
  9. title: Text('My Flutter'),
  10. ),
  11. body: Center(),
  12. )
  13. );
  14. }
  15. }

执行 flutter run 运行后可以看到下图:

对比上面代码可看到顶部蓝色区域是 AppBar 这个 Widget 来控制的。

你可以自行修改 Text 里面的内容然后按 r 键通过热重载看下效果。

我们可以看到,Flutter 里面的 dart 代码一个比较明显的地方就是一个 Widget 套着一个 Widget,有点树形的样子。

比如这里

我们尝试把 AppBar 去掉,可以看到界面显示就是一片纯白的界面。

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(MyApp());
  3. class MyApp extends StatelessWidget {
  4. @override
  5. Widget build(BuildContext context) {
  6. return MaterialApp(
  7. home: Scaffold(
  8. body: Center(),
  9. )
  10. );
  11. }
  12. }

那么这里的 MaterialApp Widget 是不是必需的呢?

其实 MaterialApp 说明这个界面是按照 Material Design 的风格。

我们看下如果去掉会怎样?

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(MyApp());
  3. class MyApp extends StatelessWidget {
  4. @override
  5. Widget build(BuildContext context) {
  6. return Scaffold(
  7. body: Center(),
  8. );
  9. }
  10. }

所以说 Scaffold 这个 Widget 不能直接返回,我们需要给它外面套一层 MaterialApp。

可以看下这个链接:https://github.com/nesger/FlutterNote/issues/4

我们返回之前的状态,然后给他加一个 Hello World,看下怎样?

我们知道,Flutter 一切皆 Widget,所以需要显示 Hello World,就需要 Widget。

Widget 可以通过这个链接查看:https://flutter.io/docs/development/ui/widgets

可以看到 Text 这个 Widget

点击进入

再点击进入,可以看到介绍以及 Sample。

大家以后如果要看其他 Widget 也可以按照同样的方式学习。

当然如果时间要求比较紧的话,大家学完博客可以直接在搜索引擎输入关键字看下别人的 Sample,然后化用一下就没问题啦。

我们点击右边复制,然后简单修改如下:

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(MyApp());
  3. class MyApp extends StatelessWidget {
  4. @override
  5. Widget build(BuildContext context) {
  6. return MaterialApp(
  7. home: Scaffold(
  8. body: Center(
  9. child: Text(
  10. 'Hello World!',
  11. textAlign: TextAlign.center,
  12. overflow: TextOverflow.ellipsis,
  13. style: TextStyle(fontWeight: FontWeight.bold),
  14. ),
  15. ),
  16. ),
  17. );
  18. }
  19. }

可以看到我们将其放到 Center 这个 Widget 里面,表示居中,同时作为它的一个 child。

大家可以试下去掉 Center 会怎样,直接将 Text 作为 body,如下:

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(MyApp());
  3. class MyApp extends StatelessWidget {
  4. @override
  5. Widget build(BuildContext context) {
  6. return MaterialApp(
  7. home: Scaffold(
  8. body: Text(
  9. 'Hello World!',
  10. textAlign: TextAlign.center,
  11. overflow: TextOverflow.ellipsis,
  12. style: TextStyle(fontWeight: FontWeight.bold),
  13. ),
  14. ),
  15. );
  16. }
  17. }

可以想象应该是不居中的。

到了这里你应该可以发现,我们整个页面其实是 body 对应的 Widget 来控制的。

上面我们的例子都是 MaterialApp,是不是一定只能这个 Widget 在最外层?

不是的,只是这里 Scaffold 跟它配对而已,我们可以修改如下:

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(MyApp());
  3. class MyApp extends StatelessWidget {
  4. @override
  5. Widget build(BuildContext context) {
  6. return Center(
  7. child: Text(
  8. 'Hello, world!',
  9. textDirection: TextDirection.ltr,
  10. textAlign: TextAlign.center,
  11. overflow: TextOverflow.ellipsis,
  12. style: TextStyle(fontWeight: FontWeight.bold),
  13. ),
  14. );
  15. }
  16. }

注意多了一行textDirection: TextDirection.ltr,没有会报错。

3. 以 Text 为例子初窥 Widget 写法

我们点进去 Text 源码看下,

对比一下上面我们的代码:

  1. Text(
  2. 'Hello, world!',
  3. textDirection: TextDirection.ltr,
  4. textAlign: TextAlign.center,
  5. overflow: TextOverflow.ellipsis,
  6. style: TextStyle(fontWeight: FontWeight.bold),
  7. )

我们可以这样认为,括号里面的是待传入参数。其中没有花括号{}包裹的是必填项,有花括号{}的是选填项。

有花括号{}的在传入参数时需要指定参数,格式为参数:值。不同参数之间逗号分隔。

所以我们可以猜测上面 Center 下面的 child 应该是在花括号里面。所以才会有上面的写法,我们跟进去源码看看。

确实跟我们猜的一样。而且由于参数的类型是 Widget,所以可以传 Text 也是没问题的。

所以到这里你再回顾一下上面是不是就知道上面代码的写法了呢?

总结

由于 Flutter UI 内容比较多,讲起来篇幅会比较大。

所以我们会拆分成几篇文章进行讲解。

回顾一下,本篇文章主要讲解如下内容:

  1. dart sdk 配置和 dart 源代码括号后面编译器提示的显示和隐藏。
  2. 通过 main.dart 的修改初步熟悉 Flutter 界面的写法。
  3. 通过 Text 说明如何在官方文档上面查找控件和对应 Sample。
  4. 通过一个具体的小控件 Text 初窥 Flutter Widget 的写法和使用方法。

小彩蛋

这个彩蛋是微信群里一个小伙伴说到的。这里分享给大家。

简单说就是设置 Android Studio 的背景图。

先上图

大家觉得哪种更加赏心悦目呢?

可以根据自己的喜好确定是否设置。

设置方法为

其中 Opacity 是不透明度。

0 表示完全透明,跟没设置一样。100 表示完全不透明。

一般默认即可。

背景图公众号回复「ASBG」获取。

更多阅读:

Flutter 即学即用系列博客——01 环境搭建

Flutter 即学即用系列博客——02 一个纯 Flutter Demo 说明

Flutter 即学即用系列博客——03 在旧有项目引入 Flutter

Flutter 即学即用系列博客——04 Flutter UI 初窥的更多相关文章

  1. Flutter 即学即用系列博客——05 StatelessWidget vs StatefulWidget

    前言 上一篇我们对 Flutter UI 有了一个基本的了解. 这一篇我们通过自定义 Widget 来了解下如何写一个 Widget? 然而 Widget 有两个,StatelessWidget 和 ...

  2. Flutter 即学即用系列博客——09 EventChannel 实现原生与 Flutter 通信(一)

    前言 紧接着上一篇,这一篇我们讲一下原生怎么给 Flutter 发信号,即原生-> Flutter 还是通过 Flutter 官网的 Example 来讲解. 案例 接着上一次,这一次我们让原生 ...

  3. Flutter 即学即用系列博客——08 MethodChannel 实现 Flutter 与原生通信

    背景 前面我们讲了很多 Flutter 相关的知识点,但是我们并没有介绍怎样实现 Flutter 与原生的通信. 比如我在 Flutter UI 上面点击了一个按钮,我希望原生做一些处理,那么原生怎么 ...

  4. Flutter 即学即用系列博客——06 超实用 Widget 集锦

    本篇文章我们来讲讲一些比较常用的 Widget. 大家验证的时候使用下面的代码替换 main.dart 代码,然后在 //TODO 语句返回下面常用 Widget 示例的代码. import 'pac ...

  5. Flutter 即学即用系列博客总结篇

    前言 迟到的总结篇,其实大家看我之前发的系列博客最后一篇,发文时间是 3 月 29 日.距离现在快两个月了. 主要是因为有很多事情在忙,所以这篇就耽搁了. 今天终于可以跟大家会面了. 系列博客背景 F ...

  6. Flutter 即学即用系列博客——09 MethodChannel 实现原生与 Flutter 通信(二)

    前言 上一篇我们讲解了如何通过 EventChannel 实现 Android -> Flutter 的通信. 并且也看到了 Flutter 内部 EventChannel 源码也是对 Meth ...

  7. Flutter 即学即用系列博客——03 在旧有项目引入 Flutter

    前言 其实如果打算在实际项目中引入 Flutter,完全将旧有项目改造成纯 Flutter 项目的可能性比较小,更多的是在旧有项目引入 Flutter. 因此本篇我们就说一说如何在旧有项目引入 Flu ...

  8. Flutter 即学即用系列博客——10 混淆

    前言 之前的博客我们都是在 debug 的模式下进行开发的. 实际发布到市场或者给到用户的都是 release 包. 而对于 Android 来说,release 包一个重要的步骤就是混淆. Andr ...

  9. Flutter 即学即用系列博客——02 一个纯 Flutter Demo 说明

    前言 上一篇文章我们搭建好了 Flutter 的开发环境. Flutter 即学即用--01 环境搭建 这一篇我们通过 Flutter 的一个 Demo 来了解下 Flutter. 开发系统:MAC ...

随机推荐

  1. bugku misc writeup(一个普通的压缩包)

    这个题做了好几个小时,因为没有writeup,一点一点摸索,做题思路写出来给大家交流 首先这是一个zip.rar压缩包,下载下来第一步就是拖进hexeditor中观察,检查下文件的头尾结构是否有问题, ...

  2. nginx常用配置系列-虚拟主机

    本来准备详尽的出一份nginx配置讲解,但nginx功能配置繁多,平常使用中使用最多的一般有: 1. 虚拟主机配置 2. HTTPS配置 3. 静态资源处理 4. 反向代理 ============= ...

  3. maven 编译出错Fatal error compiling: 无效的目标发行版: 1.8 -> [Help 1] 解决办法

    这几天在为公司项目搭建一个后台框架,使用的是eclipse-Mars自带的maven插件,在maven进行编译的时候,出现Fatal error compiling: 无效的目标发行版: 1.8 -& ...

  4. awk 手册

    1. 前言 有关本手册 : 这是一本awk学习指引, 其重点着重于 : l        awk 适于解决哪些问题 ? l        awk 常见的解题模式为何 ? 为使读者快速掌握awk解题的模 ...

  5. 将sqlserver导出的csv数据导入到ubuntu和mac上的mysql

    最近在捣鼓一些数据相关的东西.将sql server里的数据导入到ubuntu和mac上的mysql,方法有很多.不过我选择了最简单的一种:将sql server的数据导成csv,然后将csv导入到m ...

  6. LeetCode Javascript实现 258. Add Digits 104. Maximum Depth of Binary Tree 226. Invert Binary Tree

    258. Add Digits Digit root 数根问题 /** * @param {number} num * @return {number} */ var addDigits = func ...

  7. 如何将网页保存为PDF文件

    怎样将网页保存为PDF文件... 问题: 很多时候我们需要将网页上的内容,在排版不变的情况下完整的保存下来,那么用pdf格式是最好的效果了,还图文并茂,效果与真实的网页很相似,如果另存为网页的话,会下 ...

  8. Requests库作者另一神器Pipenv的用法

    前言 我们在运行 Python 项目的时候经常会遇到一些版本问题,例如 A 项目依赖于 Django 1.5,而 B 项目又依赖 Django 2.0,而我们的系统却只有一个 Python 解释器,我 ...

  9. python3.5中,import sqlite3 出现 no module named _sqlite3的解决方法

    我用的centos7.2,系统自带python2.7. 我自己装了python3.5,但在导入sqlite3这个包的时候出现找不到包的错误. 下面给出解决方法. 第一种: 检查自己有没有安装sqlit ...

  10. Java的参数传递是「值传递」还是「引用传递」?

    关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题. 有人说Java中只有值传递,也有人说值传递和引用传递都是存在的,比较容易让人产生疑问. 关于值传递和引用传递其实需要分情况看待. ...