Flutter - Weight 入门

来张野性的_回归原始

从 C 开始,我们进步到 java,再到 kotlin,现在又迎来了 Dart、Flutter,还要去学学 python。时代在进步,我们也得跟着进步,新的思想、新的工具、新的语言,速度越来越快,东西越来越多,不停学习真是 coder 这行不变的准则啊

阅读完本文推荐大家唉再去看看这篇,毕竟孤木难支,取长补短嘛~,下面这篇也是极好的:


Flutter 没有 Activity 概念

稍稍了解 Flutter 的同学都应该知道 Flutter 构建的 android 项目整个 app 只剩下 MainActivity 这一个 Activity 了,其内部使用一个 FlutterView 来承载所有的Flutter 页面,看下图:

所以 Flutter 天然的就没有页面这个概念了,Flutter 遵循 RN、前端的页面搭建思路,在 UI 这块和 android 有天壤之别,android 那种独特的写 xml 布局的方式从此是路人,历史又回归了主流

先尝个味,不要以为 Flutter 跑在 android 上就还是 android 那套,Flutter 绝逼是另一个全新的东西了。不是之前想的简简单单学学就能搞定的了,是要狠下心来耗费一番功夫的。这里我们先从 Flutter 页面搭建开始一步步深入理解 Flutter 的魅力,或者说熟悉下主流前端开发


吐槽 Flutter 的 Weight

就像 JAVA 那样一切皆对象有个口号,Flutter 也有自己的口号:一切皆 Weight,怎么理解呢,直接去看 Flutter 社区的朋友中绝对有这种表情的:

我在哪_我是谁_我来干什么

官方中文文档绝逼退治效果一流,至少我这样的就有些懵逼的感觉,其实这是大家思路停留在 android 的问题,抱着 android 的期待来学习 Flutter 绝对懵逼。要是我们当做新的语言来学习的话,静下新来仔细找找规律、思路的话反到是学起来轻松很多

android 里
  • -> 我们把 textview 写在 ConstraintLayout、LinearLayout、RelativeLayout 这样的布局容器里,然后在自己的 xml 标签里写自身的属性,宽高,位置,样式,什么样的属性都可以写,甚至还能自定义自己想要的属性进来
<android.support.constraint.ConstraintLayout
    <Button
        android:id="@+id/btn_toast"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="toast 组件"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
  • -> 然后我们用一个专门的 xml 文件来承载 UI 样式
  • -> 再然后一个 Activity 会解析处理渲染这个 xml 文件
  • -> android app 使用专门的来管理这些 Activity 的进进出出

android 的 UI 层,命名规范:布局容器都用layout结尾、内容部件都用view结尾、属性设置位置统一

Flutter 里

一切都变了:

  • Weight 不再清晰了,是像怎么叫就怎么叫
  • Weight 责任更多了,很多 Weight 组件肩负很多任务,有些相同的任务又有好几个 Weight 可供选择
  • 属性设置不再统一了,有了层级之分

当我看完 Flutter 的 Weight 之后,心里是哇凉哇凉的啊...


android 的经验一点用都没了,宝宝心里苦啊...


Flutter weight 特性

在学习 Flutter weight 之前一定要了解 Flutter weight 特性...

1. Flutter 是声明式编程

这点是和 android 有决定性差别的,Android 我们是写 xml 文件,activity 里面拿到 view 的引用,Flutter 不是的,Flutter 直接 A 代码画 UI,没了那烦人的 xml 文件。优点是:书写简便,代码少,随意性强,像怎么写怎么写。缺点是:没有预览,时间长了再看很麻烦,需要借助第三方工具查看UI 结构

  @override
  Widget build(BuildContext context) {
  
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              wordPair.asPascalCase,
            ),
            RandomWord(),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
            RaisedButton(
              onPressed: _other,
              child: Text("减一"),
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), 
    );
  }
2. Flutter weight 天然实现了数据绑定

其实这个特性也是声明式编程的一部分,拿出来说效果好一些。在 android 里面我们只能拿到 view 引用 setXXXValue 才能修改该 view 的值,想要实现响应式 UI(UI 和数据绑定)还需要接触其他组件,还要学一些额外的代码

Flutter 就没这么麻烦,Weight UI 直接就是和数据是绑定的,只要在 setValue({...}) 里面修改值就能更新 UI,看下面的例子(删除了无关代码):

class _MyHomePageState extends State<MyHomePage> {

  int _counter = 0;

  void _incrementCounter() {
    setState(() {
    _counter++;
    });
  }

  void _other() {
    setState(() {
    _counter--;
    });
  }

  @override
  Widget build(BuildContext context) {
   
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
            RaisedButton(
              onPressed: _other,
              child: Text("减一"),
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), 
    );
  }
}

一个 text 用来显示文本(count 的值),RaisedButton 按钮点一下 -1,floatingActionButton 点一下 +1,onPressed 属性配置点击方法,只要 text 组件里面引用了 count 的值就行,然后我们只要使用系统 API setState 修改值就 OK 啦

setState(() {
    _counter--;
});

Flutter 放弃 xml 结合 UI 响应式编程的思路比传统 android 方便多了,android 计就算是上了 DataBinding 在 xml 里写 UI 赋值逻辑,那也远远没 Flutter 直观啊,Flutter 又不是打开其他文件,直接就看了,多省事...程序员都是懒人,只要能偷懒,就是进步,就是优秀的

3. Flutter 对属性的拆分

这里 Flutter 是学习前端的,android 里我们可以在 xml 下对 view 配置任何属性,按照分类可以分成:宽高大小类的位置定位类的各种边距,边框,背景view 自身的属性

Flutter 把除了view 自身的属性之外的其他属性逗提升为 layout 容器级别,比如说你在 Flutter 里给一个 text 添加 padding,那么就得在这个 text 外面套上这么一层 padding 的容器

            Padding(
              padding: EdgeInsets.all(10),
              child: (Text(
                '$_counter',
                style: Theme.of(context).textTheme.display1,
              )),
            ),

就是这个样子,属性提升成了容器了,Flutter 的容器绝对了里面 view 的外观(外在属性),具体的绘制则交给了该容器内部的 weight,这看着感觉好像模板设计模式啊,外面是模板,里面是可变部分

OK,有这些打底,下面 Flutter 的 weight 就好理解了


Flutter Weight 层级划分

在 Flutter 里一切揭 Weight,Weight 像 view 一样在 Flutter 也是所有 view 的父类

Weight 按照功能划分,可以这么看:

  • 负责具体绘制的内容 Weight
  • 负责组织 Weight 样式布局 Weight,内部可以有多个子 Weight
  • 负责外在样式的修饰 Weight,内部只能有1个子 Weight

结合 android 来看的话:

  • 内容 Weight = textview 这样的 view
  • 布局 Weight = LinearLayout、RelativeLayout 这样的布局容器
  • 修饰 Weight = width、height、padding 这些属性
布局 Weight

Flutter 的 布局 Weight 比较典型的有:row、Column。row 是一行,Column 是一列

  • row 一行
class oneRow extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Row(
      mainAxisSize: MainAxisSize.max,
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: <Widget>[
        Text("AAAAAA"),
        Text("BBBBBB"),
        Text("CCCCCC"),
      ],
    );
  }
}
  • Column 一列
class oneColume extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Column(
      mainAxisSize: MainAxisSize.min,
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: <Widget>[
        Text("AAAAAA"),
        Text("BBBBBB"),
        Text("CCCCCC"),
      ],
    );
  }
}
修饰 Weight

修饰 Weight最经典的就是 Container 了,这里我们设置一个背景色

class oneContainer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Container(
      color: Colors.lightBlueAccent,
      child: oneRow(),
    );
  }
}

具体的 weight 这里就不写了,那是下一节的学习内容,通过这几个小例子让大家熟悉下 Flutter 的 Weight 结构,后面就好学多了,就算是去官方文档也会顺利很多


Flutter 如何组织页面

Flutter 虽然没有 Activity 这样的页面概念,但是 UI 出图可都是一个页面一个页面的,既然设计环节依然存在页面,那么 Flutter 也必须有页面或者相近的概念才能让我们的 UI设计图落地啊

在 Flutter 中和页面概念最接近的就是 Flutter 中唯二名字里带 Weight 的组件了:StatelessWidgetStatefulWidget

Flutter 所有的 UI、页面都是在一个 FlutterView 上显示的,大家把StatelessWidgetStatefulWidget理解为 ViewTree + viewGroup,或者直接理解成 layout 就 OK了

好比 android xml 里一层套一层的 layout,大 layout 里套小的 layout,上面 Container 的例子里,oneContainer 里面不就是套了一个 row 嘛,上面例子里我们把 layout 写成一个 class,这就是 Flutter 的自定义 viewGroup 了,大家看着简单不,省代码不

StatelessWidgetStatefulWidget的区别就是能不能在自己 layout 内部修改自己的 UI,能该的就是 StatefulWidget,不能该的必须依赖父层级修改 UI的就是 StatelessWidget

在代码上的区别就是之前提到过的 setValue 修改 UI了,StatefulWidget 里可以跑 setValue 方法,setValue 方法实际就是多次调用了 StatefulWidget 的 build 方法,StatelessWidget 反之

然后 Flutter 有专门切换 StatelessWidgetStatefulWidget显示不同页面的 API,后面讲


最后

本文其实并不是直接去学习如何使用 Flutter Weight,而是尝试梳理下 Flutter 中 Weight 的分类,相互关系,提供给看了 Flutter 有些懵或者还没有开始 Flutter 学习的朋友一些便利,希望能带给大家帮助

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容

  • 本文面向 Flutter 初学者,旨在用易懂的方式带大家入门。除了 Flutter 代码,还会介绍到语法、原理、特...
    NanBox阅读 2,748评论 0 6
  • 带你高效入门 Flutter 本文面向 Flutter 初学者,旨在用易懂的方式带大家入门。除了 Flutter ...
    叶情宇阅读 2,605评论 0 5
  • 我今年28岁,好像已经老大不小了,看看身边的同学和朋友,结婚的结婚、生娃的生娃,甚至还有准备要二胎的,可是回过头看...
    提小莫阅读 801评论 4 4
  • 1 一个月前,我给二宝小诺报了围棋兴趣班,希望学棋能让这个异常急躁的孩子,变得沉静内敛,慢慢学会控制自己的脾气。 ...
    诺曦妈妈阅读 1,694评论 2 10
  • 是不是春天一到就感觉时间紧迫? 是不是不出家门就感觉莫名心慌? 时钟滴答滴 声声响如鼓 要抓紧 要抓紧 你看柳树已...
    小五爱我阅读 109评论 0 1