flutter学习笔记(一)

flutter控件和布局

这篇博客记录一下flutter控件使用方法和常见控件库及布局方法。(吐槽一下:flutter加个边距或居中效果都得嵌套一层container之类的控件,这点不是很酷)。Flutter中一切都是widget.widget又分为无状态的控件(StatelessWidget)有状态的控件(StatefulWidget)

无状态的控件(StatelessWidget)

使用无状态的控件,需要继承StatelessWidget类,实现build方法,在build方法中返回一个布局.这个布局就是将来要展示在屏幕上的布局

常用的用来构建布局的类:

类名使用示例注释
Textnew Text(‘Hello World’, style: new TextStyle(fontSize: 32.0))创建一个显示文本的控件
Imagenew Image.asset(‘images/myPic.jpg’, fit: BoxFit.cover)从images目录下读取一个图片显示出来
Iconnew Icon(Icons.star, color: Colors.red[500])创建一个小图标
Centernew Center(child: new Text(‘Hello World’, style: new TextStyle(fontSize: 32.0))让一个Text控件居中显示
Rownew Row();创建一个行来使控件横向展示
Columnnew Column()创建一个列,让子控件纵向显示

控件常用的属性

属性名作用注释
child为当前的容器指定一个子控件并不是每一个控件都有这个属性,container,Center,BoxDecoration等控件有这个属性
children为当前控件指定多个子控件并不是每一个控件都有这个属性,ListView, GridView,Row,Column等控件有这个属性
mainAxisSize设置主轴方向的大小,如对Row来说主轴就是横向的,对column来说主轴就是纵向的常用的值包括MainAxisSize.min, MainAxisSize.max等
crossAxisSize设置副轴方向大小,如对Row来说副轴就是纵向的,对column来说副轴就是横向的常用的值包括MainAxisSize.min, MainAxisSize.max等
mainAxisAlignment设置主轴方向的对齐方式常用的值包括MainAxisAlignment.spaceEvenly,MainAxisAlignment.start,MainAxisAlignment.end, MainAxisAlignment.center等

有状态的控件(StatefulWidget)

自定义有状态的控件需要继承StatefulWidget类,实现build方法,在build方法中返回所要展示的控件效果.控件的不同状态效果是通过state来保存的.当控件的state发生改变后,可以通过setState()方法通知控件状态已经发生改变,需要重新绘制,类似于Android中的invalidate().
这里记录一个笔者遇到的坑:
在写一个有点击效果的button时,在onPressed属性后面设置点击事件时写的方法名后面带了括号,结果导致按钮无法响应点击事件,错误代码如下

IconButton(
	onPressed: _toggleFavorite(),
);

正确的代码如下

IconButton(
	onPressed: _toggleFavorite,
);

StatefulWidget的状态管理

  1. 子控件自己管理
  2. 父控件管理
  3. 子控件和父控件混合管理
子控件自己管理

请查看代码中的注释

class TapBoxA extends StatefulWidget {//TapBox是一个子控件

  @override
  State<StatefulWidget> createState() => _TapBoxAState();

}

class _TapBoxAState extends State<TapBoxA> {//TapBox用这个类来管理自己的状态
  bool _isActive = false;

  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
      onTap: _handleTap,
      child: new Container(
        child: new Center(
          child: new Text(_isActive ? "激活" : '未激活',
            style: new TextStyle(fontSize: 32.0, color: Colors.white),
          ),
        ),
        width: 200,
        height: 200,
        decoration: new BoxDecoration(
          color: _isActive ? Colors.lightGreen : Colors.grey,
        ),
      ),
    );
  }


  void _handleTap() {
    setState(() {//当状态发生变化时调用setState()来刷新控件状态
      _isActive = !_isActive;
    });
  }
}
父控件管理

可以通过注释中的数字来查看调用链条

class ParentWidget extends StatefulWidget {//父控件
  @override
  State<StatefulWidget> createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {//父控件状态管理类
  bool _active = false;

  _handleTapboxChanged(bool newValue) {
    setState(() {//父控件通过setState方法刷新界面,调用后会重走build()方法
      _active = newValue;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        child: new TapBoxB(
      active: _active,
      onChanged: _handleTapboxChanged,//3 父控件收到点击事件后调用_handleTapboxChanged方法来处理
    ));
  }
}
class TapBoxB extends StatelessWidget {//子控件,因为不需要自己管理状态所以继承StatelessWidget 
  bool active;
  ValueChanged<bool> onChanged;

  TapBoxB({Key key, this.active, this.onChanged}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
      onTap: _handleTap,//1 设置点击事件
      child: new Container(
        child: new Center(
          child: new Text(
            active ? 'Active' : 'Inactive',
            style: new TextStyle(fontSize: 32.0, color: Colors.white),
          ),
        ),
        width: 200.0,
        height: 200.0,
        decoration: new BoxDecoration(
          color: active ? Colors.lightGreen[700] : Colors.grey[600],
        ),
      ),
    );
  }

  void _handleTap() {
    onChanged(!active);//2 发生点击事件时通过onChanged方法传递给父控件
  }
}
混合管理

请阅读代码中的注释,根据注释中的数字来梳理调用链条

class ParentWidget extends StatefulWidget {//父控件
  @override
  State<StatefulWidget> createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {//父控件状态管理类
  bool _active = false;

  @override
  Widget build(BuildContext context) {
    return new Container(
      child: new TapBoxC(active: _active, onChanged: _handleTapboxCChanged),//2 父控件收到点击事件后,通过_handleTapboxCChanged处理
    );
  }

  void _handleTapboxCChanged(bool value) {
    setState(() {//3 设置_active状态,重走build方法
      _active = value;
    });
  }
}

class TapBoxC extends StatefulWidget {//子控件
  bool active;

  ValueChanged<bool> onChanged;

  TapBoxC({Key key, this.active, this.onChanged}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _TapBoxCState();
}
class _TapBoxCState extends State<TapBoxC> {//子控件状态管理类
  bool _highlight = false;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: _handleTapDown,//处理按下事件,最先发生
      onTapUp: _handleTapUp,//处理手指抬起事件,随后发生
      onTap: _handleTap,//处理点击事件,最后发生
      onTapCancel: _handleTapCancel,
      child: new Container(
        child: new Center(
          child: new Text(widget.active ? 'active' : 'inactive',
              style: new TextStyle(fontSize: 32.0, color: Colors.white)),
        ),
        width: 200,
        height: 200,
        decoration: new BoxDecoration(
            color: widget.active ? Colors.lightGreen : Colors.grey,
            border: _highlight
                ? new Border.all(color: Colors.teal, width: 10)
                : null),
      ),
    );
  }
  void _handleTapDown(TapDownDetails details) {
    setState(() {//手指按下,_highlight 设置为true,build()方法中new Border显示
      _highlight = true;
    });

  }

  void _handleTapUp(TapUpDetails details) {
    setState(() {//手指抬起,_highlight 设置为false,build()方法中new Border隐藏
      _highlight = false;
    });

  }

  void _handleTap() {
    widget.onChanged(!widget.active);//1 将点击事件通过onChanged传递给父控件处理,同时将当前控件的active状态作为参数传递出去
  }

  void _handleTapCancel() {
    setState(() {
      _highlight = false;
    });

  }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值