前言
想象一下你在叠积木。
每一个你想要摆放的都是一个 “widget”
比如官网第一段代码:
void main() {
runApp(
Center(
child: Text(
'Hello, world!',
textDirection: TextDirection.ltr,
),
),
);
}
将一个 Center 放入整个app中。center里面再放一个child Text,最后构造这个Text。
后续布局例子,完全就是杜叠积木,传送门:https://flutter.io/docs/development/ui/layout
积木(Widget)及子组件分类
- StatefulWidget:
- StatelessWidget :无状态小部件(和StatefulWidget区别有部分生命周期不一样,还有午餐构造的写法也不一样)
- 行列:这里理解起来,row是一行排列,colnum是一列排列就ok了。
- GridView
- ListView
- Stack:
- Container(容器):允许您创建矩形可视元素。可以使用BoxDecoration装饰容器 ,例如背景,边框或阴影。甲 容器还可以具有边距,填充和施加到其大小限制。另外, 可以使用矩阵在三维空间中变换容器。
- Expanded:填充剩余空间。其中的flex属性表示?
- 最小单元:IconButton,Text
- framework 提供的:Navigator
- Material Components :Scaffold/Card/ListTile
详见:https://flutter.io/docs/development/ui/widgets/material
操作
- 手势GestureDetector :onTap,onDoubleTap 等等
特点:具有onPressed 回调
详见:https://flutter.io/docs/development/ui/advanced/gestures
dart 语法 对标java 差异(特殊的)
bool : 布尔类型
num :数字类型;
numbers :数字
strings :字符串
booleans :布尔
lists (also known as arrays) :list集合(也称为数组)
maps :map集合
runes (for expressing Unicode characters in a string) :字符(用于在字符串中表示Unicode字符)
symbols :符号
raw字符串(前缀为r):避免“\”的转义作用,eg:print(r"换行符:\n"); //这个结果是 换行符:\n
typedef
superdo
assert :断言一个表达式,为假则程序立即终止。有点像throw new RunTimeException 但是表现上稍微有点怪。可用于变量检查
in
is
throw
var
const:常量类似final ,但是有一定区别,const 是编译时初始化,final是第一次用时初始化,先这么理解,这里先不做具体分析。
static const :类级别常量 static类型的变量是属于类的所以在类里面,方法之外
retthrow
with
deferred
as
dynamic
covariant
export
extenrnal
factory
get
operator
part
set
async 异步的执行某个任务
async*
await
sync*
yield
yield*
前人摘树后人乘凉:这篇博客介绍的还蛮详细的
https://blog.csdn.net/lyh1299259684/article/details/80526492
http://www.cndartlang.com/
widget 生命周期
- initState:State的子类可以覆盖initState来完成只需要发生一次的工作。
- setState:flutter 的控件刷新,状态刷新很有意思。调用 setState会将此窗口小部件标记为脏,并在下次应用程序需要更新屏幕时将其重新安排为重建。如果在修改窗口小部件的内部状态时忘记调用 setState,框架将不会知道窗口小部件是脏的,并且可能不会调用窗口小部件的 构建函数,这意味着用户界面可能不会更新以反映更改的状态。
- dispose:当不再需要状态对象时,框架会调用 状态对象上的dispose,清理工作。
- didUpdateWidget:如果您希望在窗口小部件属性更改时收到通知,则可以覆盖该函数将传递oldWidget给您以便将旧窗口小部件与当前窗口小部件进行比较 。
pubspec.yaml
官方描述:请务必uses-material-design: true在文件flutter 部分中输入一个条目pubspec.yaml。它允许您使用预定义的材料图标集
name: my_app
flutter:
uses-material-design: true
许多小部件需要在MaterialApp内部 才能正确显示,以便继承主题数据。
flutter 中的json 序列化
官方描述:https://flutter.io/docs/development/data-and-backend/json
- 对较小的项目使用手动序列化
【分析】:手动JSON解码是指使用内置的JSON解码器 dart:convert。它涉及将原始JSON字符串传递给jsonDecode() 函数,然后在结果中查找所需的值 Map<String, dynamic>。它没有外部依赖性或特定的设置过程,它有利于快速验证概念。
【使用】:https://flutter.io/docs/development/data-and-backend/json#manual-encoding
【注意】:这里只能解析一些基本类型包括
- 大型项目使用代码生成进行自动序列化
【分析】:这种方法适用于较大的项目。不需要手写的样板文件,并且在编译时捕获访问JSON字段时的拼写错误。代码生成的缺点是它需要一些初始设置。此外,生成的源文件可能会在项目导航器中产生视觉混乱。
【使用】:https://flutter.io/docs/development/data-and-backend/json
FutureBuilder
官方说明:https://docs.flutter.io/flutter/widgets/FutureBuilder-class.html
Tips官方建议。没有强制约束
- State的子类 通常以前导下划线命名,表示它们是私有实现细节。
- 为了最大限度地减少可能由嵌套严重的布局代码导致的视觉混淆,请在变量和函数中实现UI的各个部分。
QA
1,这两段代码中,沉浸式差异是体现在哪个属性上;
import 'package:flutter/material.dart';
class MyAppBar extends StatelessWidget {
MyAppBar({this.title});
// Fields in a Widget subclass are always marked "final".
final Widget title;
@override
Widget build(BuildContext context) {
return Container(
height: 56.0, // in logical pixels
padding: const EdgeInsets.symmetric(horizontal: 8.0),
decoration: BoxDecoration(color: Colors.blue[500]),
// Row is a horizontal, linear layout.
child: Row(
// <Widget> is the type of items in the list.
children: <Widget>[
IconButton(
icon: Icon(Icons.menu),
tooltip: 'Navigation menu',
onPressed: null, // null disables the button
),
// Expanded expands its child to fill the available space.
Expanded(
child: Center(
child: title,
),
),
IconButton(
icon: Icon(Icons.search),
tooltip: 'Search',
onPressed: null,
),
],
),
);
}
}
class MyScaffold extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Material is a conceptual piece of paper on which the UI appears.
return Material(
// Column is a vertical, linear layout.
child: Column(
children: <Widget>[
MyAppBar(
title: Text(
'Example title',
style: Theme.of(context).primaryTextTheme.title,
),
),
Expanded(
child: Center(
child: Text('Hello, world!'),
),
),
],
),
);
}
}
void main() {
runApp(MaterialApp(
title: 'Flutter Tutorial', // used by the OS task switcher
//home: MyScaffold(), //沉入了状态栏
home: TutorialHome(),//未沉入状态栏
));
}
class TutorialHome extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Scaffold is a layout for the major Material Components.
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.menu),
tooltip: 'Navigation menu',
onPressed: null,
),
title: Text('Example title'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
tooltip: 'Search',
onPressed: null,
),
],
),
// body is the majority of the screen.
body: Center(
child: Text('Hello, world!'),
),
floatingActionButton: FloatingActionButton(
tooltip: 'Add', // used by assistive technologies
child: Icon(Icons.add),
onPressed: null,
),
);
}
}
2,布局层级也是个问题啊,太深了
3,感觉编程模式又回到了c语言的时候,那么文件之间的相互引用又变得混乱,a引入b引入c引入d,a中莫名其妙用了d中的变量,那么要找很久。
4,错误描述:Class ‘AnimationController’ has no instance method ‘addListener’
错误场景:使用flutter 1.0 dart插件版本忘记了,本来正常工作的页面,开启debug 之后就再也 不能正常运转了。
解决方式:升级flutter 到 1.22 同时升级了andorid studio到3.3.1及flutter/dart插件,之后正常work。