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 的组件了:StatelessWidget 和 StatefulWidget

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

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

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

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

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


最后

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

最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

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

友情链接更多精彩内容