关于flutter:八天让iOS开发者上手Flutter二

Flutter布局

Alignment

Container类里有一个alignment属性,翻译过去应该叫对齐形式,这个属性用来管制Container的子控件绝对于它本身的一个地位。在咱们iOS开发中,咱们晓得坐标系的原点是在左上角。而在flutter中,坐标系的原点在父控件的正核心,能够应用这个alignment属性来管制子控件在父控件中的地位,它有两个参数别离是double类型的x,y。取值是-1到1,当0,0的时候示意子控件在父控件的正核心;当1,0的时候,示意子控件位于x方向上的最右侧,y方向上居中;当-1,-1的时候,示意子控件位于父控件的左上角地位。有点相似于CALayer的anchorPoint属性。如图代码如下:

Row

Row示意程度布局,它有一个children属性,用来寄存它的子控件。代码如下:

其中Icon类是flutter提供的一个疾速创立一些罕用图标的类。如果想给每个Icon都加一个背景色,间接设置Icon的color是不行的,这样批改的是图标的色彩而不是背景色,给Icon包一层Container容器,而后再设置Container色彩这样就能够实现了。

最开始咱们尝试了alignment属性的作用,当它是0,0的时候,Text的地位默认是在屏幕地方的。为什么这里换成咱们的Row之后,Row的子控件地位不在屏幕地方呢?

首先作为一个开发者,有一个学习的气氛跟一个交换圈子特地重要,这是一个我的iOS开发公众号:编程大鑫,不论你是小白还是大牛都欢送入驻 ,让咱们一起提高,独特倒退!(群内会收费提供一些群主珍藏的收费学习书籍材料以及整顿好的几百道面试题和答案文档!)

mainAxisAlignment

Row 和 Column 都有一个mainAxisAlignment属性,叫作主轴对齐形式,默认是MainAxisAlignment.start意思沿着主轴方向开始,Row布局下就是从左至右,Column布局下就是从上至下。
MainAxisAlignment.spaceAround:将剩下的空间平均分配
MainAxisAlignment.spaceBetween:将剩下的空间调配到子控件之间
MainAxisAlignment.spaceEvenly:等间距调配子控件

crossAxisAlignment

穿插轴对齐形式,start,end,center这几种形式试一下很好了解,stretch会将子控件拉伸。而baseline用的比拟少,独自应用它会报错,须要和Text文本联合,还须要配合textBaseline属性一起应用。如下图所示,如果不设置CrossAxisAlignment.baselineTextBaseline.alphabetic就会依据控件高度程度对齐,而如果设置了就会依据控件内文本的基线对齐。

Column

这个和Row是对应的,Row是程度布局,这个Column是垂直布局

class LayoutDemo extends StatelessWidget {
  const LayoutDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.green,
      alignment: Alignment(0, 0),
      child: Column(
        children: [
          Container(
            child: Icon(Icons.add, size: 180,),
            color: Colors.red,
          ),
          Container(
            child: Icon(Icons.ac_unit, size: 120,),
            color: Colors.yellow,
          ),
          Container(
            child: Icon(Icons.access_alarm, size: 60,),
            color: Colors.blue,
          ),
        ],
      ),
    );
  }
}
复制代码

显示成果如图:

mainAxisAlignment

这个跟Row相似

crossAxisAlignment

这个跟Row相似

Stack

这个是用在Z轴上的布局的,row是X轴,column是Y轴。children数组第一个放在最底部,最初一个放在下面,离用户最近的中央。

class LayoutDemo extends StatelessWidget {
  const LayoutDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.green,
      alignment: Alignment(0, 0),
      child: Stack(
        children: [
          Container(
            child: Icon(Icons.add, size: 180,),
            color: Colors.red,
          ),
          Container(
            child: Icon(Icons.ac_unit, size: 120,),
            color: Colors.yellow,
          ),
          Container(
            child: Icon(Icons.access_alarm, size: 60,),
            color: Colors.blue,
          ),
        ],
      ),
    );
  }
}
复制代码

APP显示成果:

alignment

Stack里有一个alignment属性,它用来管制所有子控件绝对于最大那个子控件的地位

class StackDemo extends StatelessWidget {
  const StackDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: Alignment.bottomRight,
      children: [
        Container(
          child: Icon(Icons.add, size: 180,),
          color: Colors.red,
        ),
        Container(
          child: Icon(Icons.ac_unit, size: 120,),
          color: Colors.yellow,
        ),
        Container(
          child: Icon(Icons.access_alarm, size: 60,),
          color: Colors.blue,
        ),
      ],
    );
  }
}
复制代码

Positioned

Stack里配合Positioned类应用的话,跟咱们iOS的束缚有点相似了,能够设置上,左间距之类的

class StackDemo extends StatelessWidget {
  const StackDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Positioned(
          child: Container(
            child: Icon(
              Icons.add,
              size: 180,
            ),
            color: Colors.red,
          ),
        ),
        Positioned(
          child: Container(
            child: Icon(
              Icons.ac_unit,
              size: 120,
            ),
            color: Colors.yellow,
          ),
        ),
        Positioned(
          top: 20,
          left: 20,
          right: 20,
          child: Container(
            child: Icon(
              Icons.access_alarm,
              size: 60,
            ),
            color: Colors.blue,
          ),
        ),
      ],
    );
  }
}

能够看到最小的蓝色视图的上左右均设置了20的间距,是不是相熟的束缚滋味。。。

Expanded

Expanded是一个相似Container的罕用的布局容器,它用来填充布局,应用了填充布局在主轴方向上是不会有距离的,所以Expanded用在Row外面的时候,子控件的宽度设置就没有意义了,而在Column外面应用的应用,子控件的高度设置就没有意义了。这里以Column为例:

class LayoutDemo extends StatelessWidget {
  const LayoutDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.green,
      alignment: Alignment(0, 0),
      child: Column(
        children: [
          Expanded(
              child: Container(
                child: Icon(Icons.add, size: 180,),
                color: Colors.red,
              ),
          ),
          Expanded(
              child: Container(
                child: Icon(Icons.ac_unit, size: 120,),
                color: Colors.yellow,
              ),
          ),
          Expanded(
              child: Container(
                child: Icon(Icons.access_alarm, size: 60,),
                color: Colors.blue,
              ),
          ),
        ],
      ),
    );
  }
}
复制代码

AspectRatio

AspectRatio是一个容器类,它有一个属性aspectRatio示意宽高比。如果指定了宽度,依据这个aspectRatio能够主动算出高度;如果指定了高度,依据aspectRatio能够主动算出宽度。如上面代码指定了父视图高度为100,aspectRatio宽高比为2,子视图宽度就是200,再把父视图撑起来也是200。

class LayoutDemo extends StatelessWidget {
  const LayoutDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
        color: Colors.green,
        alignment: Alignment(0, 0),
        child: Container(
          color: Colors.blue,
          height: 100,
          child: AspectRatio(
            aspectRatio: 2,
            child: Icon(
              Icons.add,
            ),
          ),
        ));
  }
}

Flutter状态治理

之前介绍的这么多类都是无状态的,意思是显示之后没方法更新UI的,如果想要实时更新UI的话,就不能继承无状态的类了。咱们先来看一个例子:明明count变动了,然而界面显示没有变动

记得批改APP的home视图

而后点击屏幕右下角的加号按钮,能够发现明明控制台打印了count的值曾经产生了变动,然而界面显示仍然是0

上面咱们解决这个问题,将StateManagerDemo继承改为StatefulWidget,实现createState办法返回一个自定义的State对象,自定义的State对象外面实现build办法。还须要留神在按钮的点击办法里调用一下setState办法。这样每次点击加号按钮就能实时更新UI了。革新完之后如下图所示:

我的项目搭建之底部TabBar

到目前为止,咱们对flutter的一些基础知识就算是介绍的差不多了。接下来咱们开始做一个简略的仿微信APP。咱们应该都有教训,实践的常识学得再多,不入手开始敲代码,不在我的项目中使用,是很难真正把握一门常识的。

新建一个flutter工程,命名wechat_demo:

删掉多余的代码,能够全副从新本人写:

创立底部的TabBar和item,默认的type是红色的,显示成果很难看所以改为fixed,还能够设置fixedColor:

这样底部的TabBar就显示进去了,会发现点击没有成果,比照iOS会发现这块中央还是iOS提供的UITabBarController封装的更难受,每个平台都各有优劣吧。

BottomNavigationBar有一个属性currentIndex即代表了以后选中的下标。咱们能够通过设置它的值来管制哪个按钮被选中。既然须要扭转UI了,阐明咱们须要将StatelessWidget改为StatefulWidget了。还有一个参数onTap是用来回调点击事件的。实现点击事件,切换currentIndex,从新setState就能够实现,点击切换了。咱们将bottomNavigationBar相干代码放到一个新的文件rootPage中。代码如下:

记得批改main.dart文件中

这样就实现了APP的底部TabBar的展现,点击性能。点击每个item的时候,会发现flutter的bottomNavigationBar还自带了动画成果…

咱们晓得Scaffold还有一个body的属性,示意展现在屏幕上的内容。咱们每个item对应的界面都须要一个AppBar,那么兴许意味着,body属性还须要一个Scaffold来展现咱们的每个item对应的内容。

能够看到微信首页就曾经大略进去了,然而点击的时候只会显示这个微信页面,怎么实现切换不同的页面呢,必定须要一个数组,来寄存对应的每个页面了。

而后body里,依据咱们的_currentIndex返回对应的body

这样点击每个item都会跳转到对应的界面了,APP的主框架的搭建好了。

总结

明天次要讲了flutter的三大布局类Row,Column,Stack以及他们的一些属性。而后是有状态的Widget和无状态的Widget,最初搭建了一下咱们要做的仿微信APP的底部bottomNavigationBar和切换页面性能。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理