设为首页 加入收藏

TOP

Flutter 布局详解(二)
2019-09-01 23:15:12 】 浏览:53
Tags:Flutter 布局 详解
被调用后,State对象不能够被构建。

State LifeCycle

完整生命周期如下:

  • 创建一个State对象时,会调用StatefulWidget.createState;
  • 和一个BuildContext相关联,可以认为被加载了(mounted);
  • 调用initState;
  • 调用didChangeDependencies;
  • 经过上述步骤,State对象被完全的初始化了,调用build;
  • 如果有需要,会调用didUpdateWidget;
  • 如果处在开发模式,热加载会调用reassemble;
  • 如果它的子树(subtree)包含需要被移除的State对象,会调用deactivate;
  • 调用dispose,State对象以后都不会被构建;
  • 当调用了dispose,State对象处于未加载(unmounted),已经被dispose的State对象没有办法被重新加载(remount)。

3.2.2 setState

State中比较重要的一个方法是setState,当修改状态时,widget会被更新。比方说点击CheckBox,会出现选中和非选中状态之间的切换,就是通过修改状态来达到的。

查看setState源码,在一些异常的情况下将会抛出异常:

  • 传入的为null;
  • 处在defunct阶段;
  • created阶段还没有被加载(mounted);
  • 参数返回一个Future对象。

检查完一系列异常后,最后调用代码如下:

_element.markNeedsBuild();

markNeedsBuild内部,则是通过标记element为diry,在下一帧的时候重建(rebuild)。可以看出setState并不是立即生效,它只是将widget进行了标记,真正的rebuild操作,则是等到下一帧的时候才会去进行。

3.3 StatefulWidget和StatelessWidget

StatefulWidget和StatelessWidget如下所示

StatefulWidget和StatelessWidget

一个StatelessWidget可以用多个不同的BuildContext构建,而一个StatefulWidget会为每个BuildContext创建一个State对象。

3.3.1 StatelessWidget

对于StatelessWidget,build方法会在如下三种情况下调用,

  1. widget第一次被插入到树中;
  2. widget的父节点更改了配置(configuration);
  3. widget依赖的InheritedWidget改变了。
class GreenFrog extends StatelessWidget {
  const GreenFrog({ Key key }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return new Container(color: const Color(0xFF2DBD3A));
  }
}

3.3.2 StatefulWidget

StatefulWidget的两个主要类别:

  1. 在initState中创建资源,在dispose中销毁,但是不依赖于InheritedWidget或者调用setState方法,这类widget基本上用在一个应用或者页面的root;
  2. 使用setState或者依赖于InheritedWidget,这种在营业生命周期中会被重建(rebuild)很多次。
class YellowBird extends StatefulWidget {
  const YellowBird({ Key key }) : super(key: key);

  @override
  _YellowBirdState createState() => new _YellowBirdState();
}

class _YellowBirdState extends State<YellowBird> {
  @override
  Widget build(BuildContext context) {
    return new Container(color: const Color(0xFFFFE306));
  }
}

4. 如何布局

每个页面设计都不一样,相同页面可选择的布局方式也不一样,如果单纯的说应该如何去布局,我觉得不现实,大家可以参考下Flutter官方的布局教程。接下来,笔者,通过一个简单的页面,来一步一步的拆解布局的流程。整个过程,基本上按照拆解、组件封装、具体布局这三步来的。

4.1 拆解

拆解

4.1.1 整体拆解

根据设计图,可以看出整体时分行展示的,因此最外层是一个Column元素

  • 第一行为标题,涉及到不对称的布局,可以用一个Stack或者Row来进行,用Row的话,则需要右边填上一个空白的widget占位。也可能会使用AppBar,将底部阴影去掉也能实现相同效果;
  • 第二行可以看作一个Row,分两块布局。右边部分,涉及到叠加,会考虑Stack;
  • 第三行比较复杂,整体看,也是一行一行进行展示的,因此最外层时一个Column。中间的文本部分需要根据个数自动换行,因此考虑使用Wrap。预习这个地方涉及到叠加,考虑Stack实现;
  • 第四行可以看作一个Row,分三块进行布局;
  • 第五行可以看作一个Row,分两块布局。

每一行之间的间隔,则可以考虑用Padding或者Container来设置。

通过上面这样一步一步的分析后,基本上对大致的布局有了一个了解,最外层的控件大致选对(只要能实现的话,就是复杂度以及效率的问题),然后一步一步的拆解每一行的元素,如果有重复的或者觉得可以封装出来的部分,则进行下一步。

4.1.2 局部拆解

每一行的拆解,大致也是按照这个思路来进行,因此笔者在这里就不做讲解了。

4.2 组件封装

例如上面,笔者想对第四行的这种展示进行封装,觉得今后的布局可能会用到,因此在这一步,可以先把这一块儿抽离出一个控件。利用Row的mainAxisAlignment以及Expanded来实现这种效果,具体的实现笔者不再详细的描述了。

经过这一步,整体的规划设计图已经有了,各个组件也都有了,接下来的工作就是组装了。

4.3 具体布局

具体布局设计到一些细节的地方,例如间隔(Padding或者Container)、居左居右居中(Align)、点击事件(GestureDetector)以及圆角(ClipRRect)等一些特殊情况,基本上就是嵌套,一层一层去实现。

在实际布局中,笔者实际使用的是Scaffold,顶部的AppBar将阴影直接去掉即可实现效果,body部分则实现2-5行的内容。最外层套一个Column也能实现,本质上都没什么区别,运行效果图如下所示。

实际运行效果

4.4 代码

代码Github地址

5. 后话

笔者建了一个flutter学习相关的项目,Github地址,里面包含了笔者写的关于flutter学习相关的一些文章,会定期更新,也会上传一些学习demo,欢迎大家关注。

6. 参考

  1. Layout Widgets
  2. Dealing with box constraints in Flutter
  3. Flutter样式和布局控件简析(一)
  4. widgets library
  5. 在Flutter中构建布局
首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Flutter 布局(二)- Padding、Al.. 下一篇不需要再手写 onSaveInstanceStat..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目