8天让iOS开发者上手Flutter之一:快速入门Flutter

·  阅读 2260

flutter现在是越来越火了,现在作为一个iOS开发,如果你不会flutter都好像不算个正常人似的?而且现在的flutter情况,有点像2012年那会儿刚刚兴起的iOS,Android开发一样,会点皮毛UI就可以提升不少身价...这些年过来,有无数的前端跨平台框架兴起。却只有flutter一家独秀,说明它还是有两把刷子的。今天这篇文章内容是基于Mac和Android Studio基础来开发flutter的,如果你还没有配置好开发环境,可以在网上搜索,或者直接到官网安装。这篇文章主要用来记录我学习flutter的过程,如果你也对flutter感兴趣可以跟着一起练习。

配置好Flutter环境之后,开始创建我们的第一个Flutter工程

创建第一个Flutter工程

打开iTerm2,cd到~/AndroidStudioProjects目录,输入以下命令,没有iTerms的使用Mac系统自带的Terminal也行。
flutter create flutter_demo
这里需要注意,AndroidStudio项目名称不能使用大写字母,这里推荐使用小写字母加下划线给工程命名。 image.png 打开对应的目录,可以看到新建了一个flutter_demo目录 image.png
接下来,cd到flutter_demo目录,在终端输入flutter run命令,它就会运行项目,如果你电脑连接了真机,就会自动运行到真机上,没有真机会去寻找模拟器并运行,模拟器也没有,就会打开一个Chrome网页运行项目(flutter项目目前可以运行在iOS,Android,web上)。我这里连上了iPhone真机,运行项目会报一个BUILD FAILED的错误: image.png 原因是flutter_demo项目生成的iOS项目默认的bundle identifier咱们用不了,去iOS项目里面修改一下就好了 image.png 这里注意我们免费的开发者证书,在iPhone上最多安装3个开发中的APP,多了就安装不了,删掉之前的APP就好了,再次运行flutter run image.png 可以看到这里给出了flutter运行的一些关键命令,Hot reload热重载,这个特性对我们开发UI时还是比原生的体验好不少的,它不用我们重新运行项目就能看到UI的一些改变。Hot restart热重启,意思不用退出APP,就直接重新运行了。此时真机上就打开了我们的第一个flutter工程的APP

HelloFlutter

上面是通过命令创建一个flutter项目,当然在实际开发过程我,我们一般不会这么操作。使用Android Studio来创建flutter项目。没有这个选项的同学,在Android Studio的插件里面选择flutter并安装就有了,如果提示还需要安装Dart就一块安装了,flutter使用的是Dart语言。iOS开发者没必要被这个新语言给吓到了,现代的语言基本都差不了太多,敲着敲着就熟悉了 image.png 点击后会出现以下界面,目前我们选择Flutter App就好了 image.png 下一个界面会让我们设置工程名称,工程位置,工程描述,工程组织,Android语言,iOS语言等等...我这里设置工程名称为hello_flutter,其他的默认选择就好了...也可以根据你自己的需要选择 image.png 点击Finish之后就可以看到完整的工程目录了,flutter工程的主入口,跟我们iOS项目一样有一个main.m文件,flutter的是main.dart文件,可以看到这个文件里面已经有不少初始的代码了,今天是我们第一次接触flutter项目,就不要这里的代码,全部删掉,我们从第一行代码开始自己敲出来 image.png

image.png

  • 导入material.dart头文件(相当于iOS中UIKit)
  • 写一个main()函数作为主入口
  • 调用runAPP()函数
  • Center类是用来布局的类,表示一个位置,child属性表示他有的子控件的意思。Text类就是我们文本类,有点儿我们iOS的UILabel的意思,Text类的第一个参数就是具体的文本,省略了参数名,第二个参数textDirection表示文本显示方向,我们习惯的从左至右就是TextDirection.ltr,left to right。像一些阿拉伯语言,希伯来语的文字就是从右到左显示的,我这里试了一下hello world的方向并没有变化,可能还需要其他设置吧...

运行之后iPhone显示如下:

自定义Widget

flutter里面的Widget类叫作小部件,是flutter里面经常用到的,它分为有状态的Stateful和Stateless无状态的。其中无状态的比较简单,我们先自定义一个类CustomWidget继承自StatelessWidget。我们自定义的Widget想要显示到屏幕上需要实现一个build的函数,系统会调用这个函数来渲染我们想要显示到屏幕上的内容 image.png 这个时候,如何将我们的hello flutter显示到屏幕呢,可以看到runApp函数里面有一个Center类,我们CustomWidget类的build方法也是返回的一个Center类,所以可以直接将我们CustomWidget初始化给runApp作参数 image.png 有些时候,我们发现hot reload无法更新界面,可以使用hot restart,如果hot restart还是无法更新界面,那就需要重新运行一下就可以了。此时我们发现main()函数里面就只有一句调用runApp()代码,在Dart语言中,函数定义如果只有一句代码,那么可以省略成如下箭头形式 image.png

设置文字样式style

按住command再用鼠标左键点击Text类,就会跳到一个text.dart文件,会看到一个this.style属性,再次按住command点击,会来到style的声明部分: image.png 这里的final表示不可变,常量的意思,类似于Swift里面的let。可以看到style是一个TextStyle类型,查看TextStyle类,会发现里面很多的属性,比如color,backgroundColor,fontSize,fontWeight...这些都是很熟悉的属性,接下来我们设置一下hello flutter的一些文字样式 image.png 使用Android Studio快捷键command + \查看界面

Material App

在flutter提供的头文件material.dart中,提供了一个快速构建APP的类型MaterialApp,我们可以使用它来快速构建一个APP的基础框架。
我们先新建一个App类来写我们的代码 image.png
然后我们在App的build方法中,返回一个MaterialApp类,如果MaterialApp不传入任何参数的话,运行后会发现APP整个屏幕变成红色,并且显示了一行文字,意思是出错了之类的,说明我们的MaterialApp应该是需要传入一个必要的参数的。 image.png 没错就像我们iOS的APP同样需要一个rootViewController一样,MaterialApp函数需要一个home参数,home参数可以传一个Widget类,如果传入我们刚刚写的CustomWidget类,运行后发现有了一点不一样的地方

右上角有一个debug的图标,hello flutter下面也出现了两条横线。

flutter还提供了一个Scaffold的类,这个类翻译过来叫作脚手架,有点像是我们iOS中的一些基础控制器(比如UITabBarController,UINavigationController)的封装。我们来使用一下这个类,这个Scaffold类有一个appBar的属性,这个属性就跟我们的UINavigationController的UINavigationBar一样,appBar是一个AppBar类型,它的title属性可以传入一个Widget,我们传入一个Text类试试看。Scaffold类除了appBar属性,还有一个body属性表示的内容,把这个body设置为我们刚刚的CustomWidget,看看是什么效果,代码如下: image.png APP上显示效果:

这个时候,是不是发现像那么回事了

MaterialApp还有一个theme的属性,这个属性用了配置app的主题,设置一下主题颜色代码如下: image.png APP上显示效果:

初探ListView

在探索ListView之前,我们先把模型实现一下,我们这里展示的一组关于汽车的图片和名字,就定义一个Car类,我们新建一个car文件用来存放我们的模型代码,代码如下: image.png

再定义一个数组,用来存放一组汽车模型,我这里放了一组网络图片,你可以直接使用,也可以自己在网上找几张图片,填入模型数组中

final List<Car> cars = [
  Car(
    name: '保时捷918 Spyder',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-7d8be6ebc4c7c95b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '兰博基尼Aventador',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-e3bfd824f30afaac?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '法拉利Enzo',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-a1d64cf5da2d9d99?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: 'Zenvo ST1',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-bf883b46690f93ce?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '迈凯伦F1',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-5a7b5550a19b8342?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '萨林S7',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-2e128d18144ad5b8?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '科尼赛克CCR',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-01ced8f6f95219ec?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '布加迪Chiron',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-7fc8359eb61adac0?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '轩尼诗Venom GT',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-d332bf510d61bbc2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '西贝尔Tuatara',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-3dd9a70b25ae6bc9?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  )
];
复制代码

然后回到main.dart文件新建一个Home类,用来存放我们ListView相关代码,和Xcode一样Android Studio同样有代码块功能,直接输入stl就会出现提示,回车就会生成StatelessWidget类相关代码。我们将Scaffold相关的代码挪到Home中来。 image.png

接下来就是正式开始使用ListView了,ListView跟其他一般的类不太一样,它的初始化需要调用build方法,并且传入两个参数,一个是itemCount,一个是itemBuilder,有点类似我们UITableView的cellForRow方法,只不过我们UITableView使用的是代理的设计,而这里的ListView使用的代码块回调的设计。

这里说一个Android Studio的比Xcode好用的地方,如图的itemCount使用了cars.length但是提示cars报错,是因为没有导入car.dart文件,给了个小红灯泡。这个时候,我们光标移动到Car类上,然后使用option + 回车会弹出一个菜单,再按一次回车就可以导入我们的car.dart文件了 image.png

itemBuilder属性就是一个代码块,用来配置每个item的样式,我们可以先统一返回一个Text文本看看效果。 image.png 显示效果就是类似于tableView一样的一行行的文本

接下来介绍一个类似于UIView的容器类Container,它跟UIView类似,可以设置一些颜色,间距,子控件之类的,我们来试一下,将Text改为Container,child属性就是子控件的意思,再给child设置为Text,文本就是cars里面的name,代码如下: image.png 再看一下显示效果

那么如果我们现在想要显示图片加文字的话应该怎么做呢?这里再介绍一个Column类,和前面介绍Center类类似,同样是属于布局的类,Column表示上下的布局,因为我们想把图片和文字上下摆放,所以需要用到Column这个类。然后关于图片的显示,这里我们先不讲怎么去网络请求,而是直接使用Image类提供的一个方法去加载网络图片,代码如图: image.png 显示效果如图:

这个时候,你应该也猜到了,如果挪动children里面Text和Image和顺序,会发现图片和文字的顺序就交换了,是不是很容易理解。如果想要调整图片和文字之间的间距怎么调呢,使用SizedBox类,传一个height就可以调整间距了,也可以继续使用Container,代码如下: image.png

如果觉得itemBuilder的代码太长,也可以将它的代码封装到一个方法里面,例如我这里使用iOS中的_cellForRow来命名这个方法。使用下划线的意义的是表示这是一个私有方法。 image.png

APP右上角会发现有一个debug图标,这个图标的显示在MaterialApp类里面有一个属性可以控制显示隐藏。 debugShowCheckedModeBanner: false

常用Widget介绍

在介绍常用Widget之前,我们想把刚刚写的ListView相关代码,封装到一个文件内,这样方便以后我们回头学习。listView_demo代码如下: image.png 这个时候,main.dart文件内的Home类的build方法里,返回我们的ListViewDemo初始化方法就行了。

然后再新建一个新的base_widget文件,用来存放我们将要介绍的基础Widget代码。 image.png 可以在main.dart文件中直接使用我的BaseWidgetDemo初始化方法,这样我们就不需要再去main.dart文件修改代码了。每介绍一个新Widget直接修改BaseWidgetDemo的build方法返回值为我们的自定义类xxxDemo()就好了 image.png

第一个介绍是Text

Text

image.png Text我们一开始讲过了,这里就再讲一点关于字符串相关的,如果需要拼接字符串可以使用$符号,如果字符串中有特殊符号,那就使用${}。其他Text常用的属性,跟我们iOS中都差不太多,需要注意的是Text的样式,是在style里面设置的。下面看一下APP显示的效果

RichText

RichText就是富文本,它的text属性可以传一个TextSpan的类,这个TextSpan类可以设置text文本,设置style样式,还可以设置children子控件,这样就可以无限加花样拼接各种字符串在一起,代码如下 image.png APP上显示的效果:

Container,Row

Container是个容器,Row是个用于布局的类,跟Column,Center类似,根据代码查看一下APP的显示,就能大概明白意思了,代码如下: image.png APP显示如下:

总结

今天介绍了Flutter里面的许多的基础Widget,有用于布局的Center,Row,Column...有用于显示文本的Text,RichText,TextSpan...有列表展示ListView,有基础架构Scaffold,MaterialApp类,虽然东西有点多,但基本还没有什么难以理解的内容

分类:
iOS
标签:
分类:
iOS
标签:
收藏成功!
已添加到「」, 点击更改