2019-06-01 27 Flutter

Widget

  • runApp函数接受Widget, 并使其成为Widget的根
  void main() {
    runApp(
      ...
    );
  }
  • StatelessWidget, 例如IconText等无状态Widget, 需要复写Widget#build()函数

  • StatefulWidget, 与用户交互或随时间变化, 当Widget改变时, 调用setState()通知框架重绘widget, 自定义StatefulWidget需要创建StatefulWidgetState

  // 实例,
  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'),
            ),
          ),
        ],
      );
    }
  }
  • 管理状态
    1. Widget管理自己的状态, 在手势(事件响应)中, Widget在类中响应(setState())刷新UI
    2. Widget管理 Widget状态, 在手势(事件响应)中, 需要父Widget更新, 则把状态由父Widget管理, 子Widget把事件回调给父Widget
    3. 混搭管理, 父Widget和子Widget共同响应刷新UI

布局

  1. 行(Row)水平排布, 列(Column)垂直排布, 包含mainAxisAlignment主轴和crossAxisAligment交叉轴对齐属性, 类似Android的LinearLayout
    • 来自flutter中文官网
    • 来自flutter中文官网
  2. ExpandWidget控制沿主轴方向的widget大小, 通过调整ExpandWidget#flex属性,默认是1, 类似CSS的flex

  3. 拥有单子元素的布局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!')),
      )
    
  1. 多个子元素的布局
    • 常用的如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'];
    }
    ...
  }

调试

参考