Flutter 即学即用系列博客——04 Flutter UI 初窥
前面三篇可以算是一个小小的里程碑。
主要是介绍了 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 的代码。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My Flutter'),
),
body: Center(),
)
);
}
}
实际编译器可能会显示如下图,就是会有注释显示每个控件。
这有好处也有坏处。好处就是你可以看到哪一块是哪一个 Widget。坏处就是视觉干扰。
这个是自动产生的,不可删除。
可以通过如下操作控制是否显示:
Android Studio->Preferences->Editor->General->Appearance
2. main.dart 学习
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My Flutter'),
),
body: Center(),
)
);
}
}
执行 flutter run 运行后可以看到下图:
对比上面代码可看到顶部蓝色区域是 AppBar 这个 Widget 来控制的。
你可以自行修改 Text 里面的内容然后按 r 键通过热重载看下效果。
我们可以看到,Flutter 里面的 dart 代码一个比较明显的地方就是一个 Widget 套着一个 Widget,有点树形的样子。
比如这里
我们尝试把 AppBar 去掉,可以看到界面显示就是一片纯白的界面。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(),
)
);
}
}
那么这里的 MaterialApp Widget 是不是必需的呢?
其实 MaterialApp 说明这个界面是按照 Material Design 的风格。
我们看下如果去掉会怎样?
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(),
);
}
}
所以说 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,然后化用一下就没问题啦。
我们点击右边复制,然后简单修改如下:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Text(
'Hello World!',
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.bold),
),
),
),
);
}
}
可以看到我们将其放到 Center 这个 Widget 里面,表示居中,同时作为它的一个 child。
大家可以试下去掉 Center 会怎样,直接将 Text 作为 body,如下:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Text(
'Hello World!',
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.bold),
),
),
);
}
}
可以想象应该是不居中的。
到了这里你应该可以发现,我们整个页面其实是 body 对应的 Widget 来控制的。
上面我们的例子都是 MaterialApp,是不是一定只能这个 Widget 在最外层?
不是的,只是这里 Scaffold 跟它配对而已,我们可以修改如下:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text(
'Hello, world!',
textDirection: TextDirection.ltr,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.bold),
),
);
}
}
注意多了一行textDirection: TextDirection.ltr,没有会报错。
3. 以 Text 为例子初窥 Widget 写法
我们点进去 Text 源码看下,
对比一下上面我们的代码:
Text(
'Hello, world!',
textDirection: TextDirection.ltr,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.bold),
)
我们可以这样认为,括号里面的是待传入参数。其中没有花括号{}包裹的是必填项,有花括号{}的是选填项。
有花括号{}的在传入参数时需要指定参数,格式为参数:值。不同参数之间逗号分隔。
所以我们可以猜测上面 Center 下面的 child 应该是在花括号里面。所以才会有上面的写法,我们跟进去源码看看。
确实跟我们猜的一样。而且由于参数的类型是 Widget,所以可以传 Text 也是没问题的。
所以到这里你再回顾一下上面是不是就知道上面代码的写法了呢?
总结
由于 Flutter UI 内容比较多,讲起来篇幅会比较大。
所以我们会拆分成几篇文章进行讲解。
回顾一下,本篇文章主要讲解如下内容:
- dart sdk 配置和 dart 源代码括号后面编译器提示的显示和隐藏。
- 通过 main.dart 的修改初步熟悉 Flutter 界面的写法。
- 通过 Text 说明如何在官方文档上面查找控件和对应 Sample。
- 通过一个具体的小控件 Text 初窥 Flutter Widget 的写法和使用方法。
小彩蛋
这个彩蛋是微信群里一个小伙伴说到的。这里分享给大家。
简单说就是设置 Android Studio 的背景图。
先上图
大家觉得哪种更加赏心悦目呢?
可以根据自己的喜好确定是否设置。
设置方法为
其中 Opacity 是不透明度。
0 表示完全透明,跟没设置一样。100 表示完全不透明。
一般默认即可。
背景图公众号回复「ASBG」获取。
更多阅读:
Flutter 即学即用系列博客——01 环境搭建
Flutter 即学即用系列博客——02 一个纯 Flutter Demo 说明
Flutter 即学即用系列博客——03 在旧有项目引入 Flutter
Flutter 即学即用系列博客——04 Flutter UI 初窥的更多相关文章
- Flutter 即学即用系列博客——05 StatelessWidget vs StatefulWidget
前言 上一篇我们对 Flutter UI 有了一个基本的了解. 这一篇我们通过自定义 Widget 来了解下如何写一个 Widget? 然而 Widget 有两个,StatelessWidget 和 ...
- Flutter 即学即用系列博客——09 EventChannel 实现原生与 Flutter 通信(一)
前言 紧接着上一篇,这一篇我们讲一下原生怎么给 Flutter 发信号,即原生-> Flutter 还是通过 Flutter 官网的 Example 来讲解. 案例 接着上一次,这一次我们让原生 ...
- Flutter 即学即用系列博客——08 MethodChannel 实现 Flutter 与原生通信
背景 前面我们讲了很多 Flutter 相关的知识点,但是我们并没有介绍怎样实现 Flutter 与原生的通信. 比如我在 Flutter UI 上面点击了一个按钮,我希望原生做一些处理,那么原生怎么 ...
- Flutter 即学即用系列博客——06 超实用 Widget 集锦
本篇文章我们来讲讲一些比较常用的 Widget. 大家验证的时候使用下面的代码替换 main.dart 代码,然后在 //TODO 语句返回下面常用 Widget 示例的代码. import 'pac ...
- Flutter 即学即用系列博客总结篇
前言 迟到的总结篇,其实大家看我之前发的系列博客最后一篇,发文时间是 3 月 29 日.距离现在快两个月了. 主要是因为有很多事情在忙,所以这篇就耽搁了. 今天终于可以跟大家会面了. 系列博客背景 F ...
- Flutter 即学即用系列博客——09 MethodChannel 实现原生与 Flutter 通信(二)
前言 上一篇我们讲解了如何通过 EventChannel 实现 Android -> Flutter 的通信. 并且也看到了 Flutter 内部 EventChannel 源码也是对 Meth ...
- Flutter 即学即用系列博客——03 在旧有项目引入 Flutter
前言 其实如果打算在实际项目中引入 Flutter,完全将旧有项目改造成纯 Flutter 项目的可能性比较小,更多的是在旧有项目引入 Flutter. 因此本篇我们就说一说如何在旧有项目引入 Flu ...
- Flutter 即学即用系列博客——10 混淆
前言 之前的博客我们都是在 debug 的模式下进行开发的. 实际发布到市场或者给到用户的都是 release 包. 而对于 Android 来说,release 包一个重要的步骤就是混淆. Andr ...
- Flutter 即学即用系列博客——02 一个纯 Flutter Demo 说明
前言 上一篇文章我们搭建好了 Flutter 的开发环境. Flutter 即学即用--01 环境搭建 这一篇我们通过 Flutter 的一个 Demo 来了解下 Flutter. 开发系统:MAC ...
随机推荐
- bugku misc writeup(一个普通的压缩包)
这个题做了好几个小时,因为没有writeup,一点一点摸索,做题思路写出来给大家交流 首先这是一个zip.rar压缩包,下载下来第一步就是拖进hexeditor中观察,检查下文件的头尾结构是否有问题, ...
- nginx常用配置系列-虚拟主机
本来准备详尽的出一份nginx配置讲解,但nginx功能配置繁多,平常使用中使用最多的一般有: 1. 虚拟主机配置 2. HTTPS配置 3. 静态资源处理 4. 反向代理 ============= ...
- maven 编译出错Fatal error compiling: 无效的目标发行版: 1.8 -> [Help 1] 解决办法
这几天在为公司项目搭建一个后台框架,使用的是eclipse-Mars自带的maven插件,在maven进行编译的时候,出现Fatal error compiling: 无效的目标发行版: 1.8 -& ...
- awk 手册
1. 前言 有关本手册 : 这是一本awk学习指引, 其重点着重于 : l awk 适于解决哪些问题 ? l awk 常见的解题模式为何 ? 为使读者快速掌握awk解题的模 ...
- 将sqlserver导出的csv数据导入到ubuntu和mac上的mysql
最近在捣鼓一些数据相关的东西.将sql server里的数据导入到ubuntu和mac上的mysql,方法有很多.不过我选择了最简单的一种:将sql server的数据导成csv,然后将csv导入到m ...
- 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 ...
- 如何将网页保存为PDF文件
怎样将网页保存为PDF文件... 问题: 很多时候我们需要将网页上的内容,在排版不变的情况下完整的保存下来,那么用pdf格式是最好的效果了,还图文并茂,效果与真实的网页很相似,如果另存为网页的话,会下 ...
- Requests库作者另一神器Pipenv的用法
前言 我们在运行 Python 项目的时候经常会遇到一些版本问题,例如 A 项目依赖于 Django 1.5,而 B 项目又依赖 Django 2.0,而我们的系统却只有一个 Python 解释器,我 ...
- python3.5中,import sqlite3 出现 no module named _sqlite3的解决方法
我用的centos7.2,系统自带python2.7. 我自己装了python3.5,但在导入sqlite3这个包的时候出现找不到包的错误. 下面给出解决方法. 第一种: 检查自己有没有安装sqlit ...
- Java的参数传递是「值传递」还是「引用传递」?
关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题. 有人说Java中只有值传递,也有人说值传递和引用传递都是存在的,比较容易让人产生疑问. 关于值传递和引用传递其实需要分情况看待. ...