2019-06-01 27 Flutter
Widget
runApp函数接受Widget, 并使其成为Widget的根
void main() {
runApp(
...
);
}
-
StatelessWidget, 例如Icon、Text等无状态Widget, 需要复写Widget#build()函数 -
StatefulWidget, 与用户交互或随时间变化, 当Widget改变时, 调用setState()通知框架重绘widget, 自定义StatefulWidget需要创建StatefulWidget和State类
// 实例,
class FavoriteWidget extends StatefulWidget {
@override
createState() => new _FavoriteWidgetState();
}
class _FavoriteWidgetState extends State<FavoriteWidget> {
...
void _toggleFavorite() {
// 通知刷新
setState(() {
if (_isFavorite) {
_isFavorite = false;
_favoriteCount -= 1;
} else {
_favoriteCount += 1;
_isFavorite = true;
}
});
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return new Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Container(
padding: new EdgeInsets.all(0.0),
child: new IconButton(
icon: _isFavorite
? new Icon(Icons.star)
: new Icon(Icons.star_border),
color: Colors.red[500],
onPressed: _toggleFavorite),
),
new SizedBox(
width: 18.0,
child: new Container(
child: new Text('$_favoriteCount'),
),
),
],
);
}
}
- 管理状态
Widget管理自己的状态, 在手势(事件响应)中,Widget在类中响应(setState())刷新UI- 父
Widget管理Widget状态, 在手势(事件响应)中, 需要父Widget更新, 则把状态由父Widget管理, 子Widget把事件回调给父Widget - 混搭管理, 父
Widget和子Widget共同响应刷新UI
布局
- 行(
Row)水平排布, 列(Column)垂直排布, 包含mainAxisAlignment主轴和crossAxisAligment交叉轴对齐属性, 类似Android的LinearLayout -
ExpandWidget控制沿主轴方向的widget大小, 通过调整ExpandWidget#flex属性,默认是1, 类似CSS的flex - 拥有单子元素的布局widget
Container, 绘制、定位、调整大小Container( constraints: BoxConstraints.expand( height: Theme.of(context).textTheme.display1.fontSize * 1.1 + 200.0, ), padding: const EdgeInsets.all(8.0), color: Colors.blue[600], alignment: Alignment.center, child: Text('Hello World', style: Theme.of(context) .textTheme .display1 .copyWith(color: Colors.white)), transform: Matrix4.rotationZ(0.1), )Padding, 给子widget添加指定填充Padding( padding: EdgeInsets.all(8.0), child: const Card(child: Text('Hello World!')), )Center, 将子widget居中显示Align, 将子widget对齐
Align(
alignment: Alignment(0.2, 0.6),
child: FlutterLogo(
size: 60,
)
)
ConstrainedBox约束布局ConstrainedBox( constraints: const BoxConstraints.expand(), child: const Card(child: Text('Hello World!')), )
- 多个子元素的布局
- 常用的如
Row,Column Stack允许子widget堆叠Stack( children: <Widget>[ Container( width: 100, height: 100, color: Colors.red, ), Container( width: 90, height: 90, color: Colors.green, ), ... ], )ListView, 滚动列表布局ListView( padding: const EdgeInsets.all(8.0), children: <Widget>[ Container( height: 50, color: Colors.amber[600], child: const Center(child: Text('Entry A')), ), Container( height: 50, color: Colors.amber[500], child: const Center(child: Text('Entry B')), ), ... ], )
- 常用的如
手势
Pointers, 表示touch, stylus, 或者mouse事件PointerDownEvent, The pointer has made contact with the device.PointerMoveEvent, The pointer has moved with respect to the device while the pointer is in contact with the device.PointerUpEvent, The pointer has stopped making contact with the device.PointerCancelEvent, The input from the pointer is no longer directed towards this receiver.
GestureDetector, 拦截事件的widget
GestureDetector(
onTap: () {
setState(() { _lights = true; });
},
child: Container(
color: Colors.yellow,
child: Text('TURN LIGHTS ON'),
),
)
动画
- 补间(Tween)动画
- 基于物理的动画
Http网络请求
import 'dart:convert';
import 'dart:io';
_getIPAddress() async {
var url = 'https://httpbin.org/ip';
var httpClient = new HttpClient();
var request = await httpClient.getUrl(Uri.parse(url));
var response = await request.close();
if (response.statusCode == HttpStatus.OK) {
var json = await response.transform(utf8.decoder).join();
var data = jsonDecode(json);
String result = data['origin'];
}
...
}

