flutter从入门到精通1

阅读文章需要10分钟~

目录

  1. 走进Flutter开发

如何高效的学习Flutter
Flutter开发环境搭建及常见问题
走进Flutter的Widget世界
如何快速上手Flutter布局
  1. Flutter混合架构原理剖析与应用

Flutter框架和原理剖析
探析Flutter渲染机制之三棵树
如何在已有的项目中集成Flutter?
Flutter与Native通信原理剖析
  1. Flutter实战应用与性能优化

复杂场景下Flutter嵌入Native组件实战
Flutter Native组件的通信功原理与实现
Flutter实战和性能优化
flutter 热更新方案探索与应用

1.走进flutter

  • 走进和认识它

  • 掌握它的语言

  • 掌握它的Widget

  • 熟悉它的状态机制

  • 调试技巧

  • 深入原理

  • 合理利用工具

认识Flutter

Flutter 是由Google 开发的一个跨平台UI开发工具包;叫它UI开发工具包主要是因为它主要聚焦在UI搭建和渲染层的事情,对于本台本身的一些功能:比如调用蓝牙、摄像头,一般还是需要原生代码去操作。但现在也会有一些第三方库帮我们解决这些问题

Flutter发展简史

  • 2014.10 - Flutter的前身Sky在GitHub上开源

  • 2015.10 - 经过一年的开源,Sky正式改名为Flutter,低调期

  • 2017.5 - Google I/O正式向外界公布了Flutter,这个时候Flutter才正式进去大家的视野

  • 2018.6 - 距5月Google I/O 1个月的时间,Flutter1.0预览版

  • 2018.12 - Flutter1.0发布,它的发布将大家对Flutter的学习和研究推到了一个新的起点

  • 2019.2 - Flutter1.2发布主要增加对web的支持

  • 2020.5 - Flutter1.17是2020年的第一个稳定版本,此版本包括iOS平台Metal支持(性能更快),新的Material组件,新的Network跟踪工具等等;

由此开看:Flutter在逐渐的走向成熟和壮大,它的生态圈也在不断的发展,所以现在学习Flutter是正当时!!!

Flutter架构

Flutter具有三个主要组成部分:

  • 框架层:Flutter框架建立在Dart语言的基础上,在Flutter中一切UI皆Widget,Flutter有两大不同风格的Widget库,一个是基于Material Design(材料设计)风格的组件库;一个是基于cupertino的iOS设计风格的组件库;

  • 引擎层:Flutter引擎使用的是基于C++的2D图形库(称为Skia)。 在这一层中,提供了Dart VM,以提供一个执行环境,用于将Dart代码转换为本地平台可执行代码。 Flutter引擎在Android,iOS中运行,以为widget呈现对应的外观,并根据特定平台通过Channel进行通信;

  • 平台层:Flutter根据不同平台提供了其特定的shell(即Android Shell和iOS Shell),这些shell用来托管Dart VM,以提供对特定的平台API的访问;

Flutter的开发语言

Flutter是基于Dart语言开发的,所以做Flutter开发我们首先要了解设熟悉Dart语言。

Dart是强类型语言,静态类型

从Dart2开始Dart便是强类型语言,而且是静态类型的,这点可以类比Java,C#。

怎么理解呢?如果在编译时已知变量的类型,则静态键入语言。那么 对于某些语言,这意味着作为开发人员必须指定每个变量的类型(例如:Java,C#);

主要优点是所有类型的检查都可以由编译器完成,因此很早就会发现许多琐碎的错误。

对于移动端同学来说因为Java和Kotlin等都是强类型静态类型语言,所以这块会比较容易上手;但对于前端开发的同学,接触到比较多的编程语言通常是JavaScript,JS是弱类型,动态类型语言,所以在前端同学在学习Dart的时候一定要分清这两个概念。

Dart是面向对象的语言

Dart是面向对象的语言,除Dart外,再为大家列举几个面向对象的编程语言:Python、C++、Objective-C、Java、Kotlin、Swift、C#、Ruby 与 PHP等。

如果你有OOP也就是面向对象编程的经验,那么学习Dart会很轻松。

对于移动端同学来说因为Java和Kotlin等都是面向对象语言所以学习Dart会轻松些;但对于前端同学来说,JavaScript不是面向对象的,所以学习Dart会有一定的适应过程,可以将Dart作为你的第一个面向对象的编程语言进行学习。

Dart的JIT&AOT

  • JIT:即时编译,开发期间,更快编译,更快的重载

  • AOT:事前编译,release期间,更快更流畅

Dart支持JIT与AOT,JIT全称 Just In Time(即时编译)Flutter在开发期间采用的是JIT,这样可以做到更快的编译与更快的代码重载;但 JIT的劣势也是显而易见的,JIT需要在运行时将代码编译成机器码,给用户带来的直接感受就是慢;你会发现在开发期间装的flutter包会有些卡顿,release之后会变好,其中一部分原因是因为AOT的存在;

AOT全称 Ahead Of Time(事前编译),典型的例子就是 C/C++,能直接编译成机器码也就是二进制代码,AOT的优势也是显而易见的,事先编译好的二进制代码,加载和执行的速度都会非常快。当你的Flutter APP release时采用的是AOT,这使得你的APP能够以更快的速度和流畅度来运行。

学习Flutter可以利用的工具

古文《荀子·劝学》中有一句名言:君子生非异也,善假于物也。所以快速高效的学习一门新知识要善假于物。在这里为大家列举了几种学习Flutter的抓手:

  • Flutter学习教程:如果你之前还没接触过Flutter或掌握的都是零散的知识,那么可以通过学习教程来快速和系统的来学习Flutter,并且可以节约你学习时间,少走弯路:

  • 官方文档:Flutter官方文档也是一个了解Flutter的不错的途径,但知识比较零散,可以上面教程进行互补:

  • Flutter插件库:Flutter无法实现的一些功能,我们可以借助一些插件来实现:

  • 常见问题:学习Flutter的过程中难免会遇到各种各样的问题,那么可以借助一些途径来解决:

2.Flutter开发环境搭建及常见问题

  • 在Windows上搭建Flutter开发环境

  • 在Mac上搭建Flutter开发环境

  • FAQ

在Windows上搭建Flutter开发环境

  • 系统要求

  • 设置FLutter镜像(非必须)

  • 获取Flutter SDK

  • Android开发环境设置

  • 安装Flutter插件

系统要求

在Windows上要安装并运行Flutter要满足以下最低要求:

  • 操作系统: Windows 7 SP1或更新版本

  • 磁盘空间: 400 MB (不包括IDE/tools的磁盘空间).

  • 工具: Flutter 依赖下面这些命令行工具:

设置FLutter镜像(非必须)

由于在国内访问Flutter可能会受到限制,Flutter官方为中国开发者搭建了临时镜像,大家可以将如下环境变量加入到用户环境变量中:

PUB_HOSTED_URL=https://pub.flutter-io.cn  
FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn  
代码块12

注意:此镜像为临时镜像,并不能保证一直可用,大家可以从 Using Flutter in China 上获得有关镜像服务器的最新动态。

获取Flutter SDK

1.点Flutter官网下载其最新可用的安装包。

2.解压安装包到你想安装的目录,如:C:\flutter

注意,不要将flutter安装到需要一些高权限的路径如 C:\Program Files\等。
设置环境变量

要在终端运行 flutter 命令, 你需要添加以下环境变量到系统PATH

  • 在Windows的Start 的搜索条中搜索env,选择编辑帐户的环境变量

  • 在“用户变量”下检查是否有名为“Path”的条目:

  • 如果该条目存在, 追加 flutter\bin的全路径,使用 ; 作为分隔符.

  • 如果条目不存在, 创建一个新用户变量 Path ,然后将 flutter\bin的全路径作为它的值.

  • 重启Windows以应用此更改;

接下来,你就可以在Flutter命令行运行flutter命令了。

运行 flutter doctor

上面path配置完成之后,打开一个新的命令提示符或PowerShell窗口并运行以下命令以查看是否需要安装任何依赖项来完成安装:

$ flutter doctor  
代码块1

该命令检查你的环境并在终端窗口中显示报告。Dart SDK已经在捆绑在Flutter里了,没有必要单独安装Dart。 仔细检查命令行输出以获取可能需要安装的其他软件或进一步需要执行的任务(以粗体显示):

例如:

[-] Android toolchain - develop for Android devices  
 • Android SDK at /Users/obiwan/Library/Android/sdk ✗ Android SDK is missing command line tools; download from https://goo.gl/XxQghQ • Try re-installing or updating your Android SDK, visit https://flutter.dev/setup/#android-setup for detailed instructions.
代码块12

一般的错误会是Android Studio版本太低、或者没有ANDROID_HOME环境变量等

第一次运行一个flutter命令(如flutter doctor)时,它会下载它自己的依赖项并自行编译。以后再运行就会快得多。

Android开发环境设置

安装Android Studio

1.下载并安装 Android Studio

因为Android网站设在国外,如果你的网络无法访问第一个地址,可以选择使用Google为中国开发者提供的中国网址进行访问。

另外,关于Android Studio的安装和配置,Android官方有比较详细的说明文档https://developer.android.google.cn/studio/intro,大家可以根据需要进行查阅;

大家在安装过程中遇到问题无法解决的,可以在我们课程的 问答区提问进行 提问

2.启动Android Studio,然后执行“Android Studio安装向导”。这将安装最新的Android SDK,Android SDK平台工具和Android SDK构建工具

Flutter插件安装
  • 打开Android Studio

  • 打开Preferences > Plugins (macOS), File > Settings > Plugins (Windows & Linux)

  • 选择 Browse repositories, 搜索 Flutter plugin

  • 然后点击安装,然后安装Dart插件

  • 完成之后选择重启Android Studio

如何在Android模拟器上运行Flutter?

要准备在Android模拟器上运行并测试您的Flutter应用,需要按照以下步骤操作:

  • 启动 Android Studio>Tools>Android>AVD Manager 并选择 Create Virtual Device

  • 选择一个设备并选择 Next;

  • 为要模拟的Android版本选择一个或多个系统映像,然后选择 Next. 建议使用 x86 或 x86_64 的镜像;

  • 在 Emulated Performance下, 选择 Hardware - GLES 2.0 以启用硬件加速;

  • 验证AVD配置是否正确,然后选择 Finish;

如果对以上步骤还有不清楚的可以参阅Android官方的 Managing AVDs文档。

大家在安装过程中遇到问题无法解决的,可以在我们课程的 问答区提问进行 提问
  • 在 Android Virtual Device Manager中, 点击工具栏的 Run,模拟器启动并显示所选操作系统版本或设备的启动画面;

  • 通过flutter run运行启动项目;

如何在Android真机运行?

要准备在Android设备上运行并测试您的Flutter应用,您需要安装Android 4.1(API level 16)或更高版本的Android设备

  • 在你的设备上启用 开发人员选项USB调试 。详细说明可在Android文档中找到;

  • 使用USB将手机插入电脑,如果有授权提示需要同意授权;

  • 在终端中,运行flutter devices 命令以验证Flutter是否识别你连接的Android设备;

  • 通过flutter run运行启动项目;

默认情况下,Flutter使用的Android SDK版本是基于你的 adb 工具版本, 如果你想让Flutter使用不同版本的Android SDK,则必须将该 ANDROID_HOME 环境变量修改SDK的目录。

创建和运行一个简单的Flutter项目

1.通过如下命令创建一个Flutter项目

$ flutter create my_app  
代码块1

2.命令运行完成之后会在当前目录下创建一个名为my_app的Flutter项目,然后通过一下命令可以运行它:

$ cd my_app  
$ flutter run  
代码块12

在Mac上搭建Flutter开发环境

考虑到有不少小伙伴在用Mac系统做开发,那么在Mac该如何搭建Flutter开发环境呢?

  • 系统要求

  • 设置FLutter镜像(非必须)

  • 获取Flutter SDK

  • iOS开发环境设置

  • Android开发环境设置

  • 安装Flutter插件

系统要求

在Mac上要安装并运行Flutter要满足以下最低要求:

  • 操作系统: macOS (64-bit)

  • 磁盘空间: 2.8 GB (不包括IDE/tools的磁盘空间).

  • 工具: Flutter 依赖下面这些命令行工具:bash curl git 2.x mkdir rm unzip which zip

设置Flutter镜像(非必须)

由于在国内访问Flutter可能会受到限制,Flutter官方为中国开发者搭建了临时镜像,大家可以将如下环境变量加入到用户环境变量中:

//Macintosh HD⁩ ▸ ⁨Users⁩ ▸ ⁨你的用户名 ▸ ⁨.bash_profile  
export PUB_HOSTED_URL=https://pub.flutter-io.cn  
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn  
代码块123

注意:此镜像为临时镜像,并不能保证一直可用,大家可以从 Using Flutter in China 上获得有关镜像服务器的最新动态。

获取Flutter SDK

1.点Flutter官网下载其最新可用的安装包。

2.解压安装包到你想安装的目录,如:

$ cd ~/development  
$ unzip ~/Downloads/flutter_macos_1.17.3-stable.zip  
代码块12

3.添加flutter相关工具到path中:

export PATH="$PATH:`pwd`/flutter/bin"```  
  
此代码只能暂时针对当前命令行窗口设置PATH环境变量,要想永久将Flutter添加到PATH中请参考下面做法:  
  
```bash  
$ cd ~  
$ vim .bash_profile  
代码块1234567

然后添加:

export PATH=/Users/你的用户名/Documents/flutter/bin:$PATH代码块1

之后记得保存文件。

运行 flutter doctor

上面path配置完成之后,需要关闭终端重新打开,然后运行:

$ flutter doctor  
代码块1

该命令检查你的环境并在终端窗口中显示报告。Dart SDK已经在捆绑在Flutter里了,没有必要单独安装Dart。 仔细检查命令行输出以获取可能需要安装的其他软件或进一步需要执行的任务(以粗体显示):

例如:

[-] Android toolchain - develop for Android devices  
 • Android SDK at /Users/obiwan/Library/Android/sdk ✗ Android SDK is missing command line tools; download from https://goo.gl/XxQghQ • Try re-installing or updating your Android SDK, visit https://flutter.dev/setup/#android-setup for detailed instructions.
代码块12

一般的错误会是XCode或Android Studio版本太低、或者没有ANDROID_HOME环境变量等,可参考一下环境变量的配置来检查你的环境变量:

//Macintosh HD⁩ ▸ ⁨Users⁩ ▸ ⁨你的用户名 ▸ ⁨.bash_profile  
#Android 环境变量  export ANDROID_HOME=/Users/你的用户名/Library/Android/sdk  
#Android 模拟器路径  export PATH=${PATH}:${ANDROID_HOME}/emulator  
#Android tools 路径  export PATH=${PATH}:${ANDROID_HOME}/tools  
#Android 平台工具路径  export PATH=${PATH}:${ANDROID_HOME}/platform-tools  
#Android NDK路径  
ANDROID_NDK_HOME=/Users/你的用户名/Library/Android/ndk/android-ndk-r10e  
#FLutter镜像  export PUB_HOSTED_URL=https://pub.flutter-io.cn  
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn  
#Flutter环境变量  export PATH=/Users/你的用户名/Documents/flutter/bin:$PATH代码块12345678910111213141516
第一次运行一个flutter命令(如flutter doctor)时,它会下载它自己的依赖项并自行编译。以后再运行就会快得多。

iOS开发环境设置

安装 Xcode

要用Flutter开发iOS App需要Xcode 9.0 或更高版本:

1.安装Xcode 9.0或更新版本(通过链接下载苹果应用商店)

2.配置Xcode命令行工具以使用新安装的Xcode版本 s

$ sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer  
代码块1

以上路径时对于最新版Xcode的路径。如果你需要使用不同的Xcode版本,需要指定相应路径。

3.确保Xcode许可协议是通过打开一次Xcode或通过命令sudo xcodebuild -license同意过了

接下来就可以使用Xcode,在iOS设备或模拟器上运行Flutter App了。

设置iOS模拟器

要准备在iOS模拟器上运行并测试您的Flutter应用,请按以下步骤操作:

1.在终端输入如下命令打开一个iOS模拟器:

$ open -a Simulator  
代码块1

2.通过模拟器菜单栏的 硬件>设备 ,确保你打开是64位 iPhone 5s或更新的模拟器

3.如果模拟器过大,可以通过模拟器的 Window> Scale 菜单下设置设备比例

创建和运行一个简单的Flutter项目

1.通过如下命令创建一个Flutter项目

$ flutter create my_app  
代码块1

2.命令运行完成之后会在当前目录下创建一个名为my_app的Flutter项目,然后通过一下命令可以运行它:

$ cd my_app  
$ flutter run  
代码块12

FAQ

无法启动模拟器

emulator: ERROR: x86 emulation currently requires hardware acceleration! Please  
ensure Windows Hypervisor Platform (WHPX) is properly installed and usable.  
CPU acceleration status: HAXM is not installed on this machine  
代码块123
解决方案:选择 Tools > SDK Manager > SDK Tools , 安装 HAXM 即可

flutter no devices loading

问题描述

在Android Studio上明明启动了模拟器但是还是提示 no devices,并且显示loading

解决办法

重启Android Studio

新发布的包下载不下来

点击packages get 一直提示:

pub get failed (69) -- attempting retry  
代码块1
解决办法

.bash_profile中取消pub的镜像:

#export PUB_HOSTED_URL=https://pub.flutter-io.cn  #export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn  代码块12

Android Studio创建Flutter项目卡死

原因分析

网络原因是导致卡死的真凶,因为Android Studio创建Flutter项目需要联网下载一些国外服务器上的依赖包。

解决办法

方案一:改为通过命令行的方式创建,亲测可行:

//创建一个名为flutter_ui的flutter项目  
flutter create flutter_ui  
//如果你想自定义包名可以通过如下方式进行  
flutter create --org org.dev.io.flutter.ui flutter_ui  
代码块1234

方案二:

  • 关闭模拟器之后重试;

  • 重启电脑后重试。

Waiting for another flutter command to release the startup lock…

解决办法

将文件

⁨flutter⁩ ▸ ⁨bin⁩ ▸ ⁨cache⁩ ⁩▸ lockfile  
代码块1

3.走进Flutter的Widget世界

在Flutter中界面上一切可以看到的元素皆是Widget,在这一节呢我们就来走进Flutter widgets世界,一起认识下在Flutter中都有哪些常见的Widget。

Flutter widgets概述

Flutter发展至今,Flutter widgets大家庭产了170多个娃;这170+的widgets中常用的不过几十个,大部分widget是冷门widget,它们中的很多都是可以用其他的widget来替代。为了方便大家学习,我们挑选了在Flutter开发过程中比较常用的一些widgets并将它们按照功能不同分为6大类,如下图:

  • 布局 Widget:主要用来排列其它的小部件的列,行,网格和许多其他布局。按照它们可容纳的子元素不同,可以将它们分为:

  • 单子元素布局widget:只能有一个child widget

  • 多子元素布局widget:可以有多个child widget

  • 文本 Widget:用来显示和设置文字样式的widget。常用的主要有两个:

  • Text:单一格式的文本控件;

  • RichText:一个富文本Text,可以显示多种样式的text;

  • 可滚动的Widget:它是一类滚动一个拥有多个子组件的父组件。常用的主要有两个:

  • ListView:一个可滚动的列表;

  • GridView:一个可滚动的网格布局列表;

  • 绘制和效果Widget:主要用来将视觉效果应用到其子组件,而不改变它们的布局、大小和位置。常用的主要有:

  • Opacity:用来改变widget透明度;

  • Transform:用来改变widget 空间位置,旋转角度等;

  • ClipXX:用来裁减widget的一类组件,比如用来裁减成圆形的ClipOval,用来裁减成矩形的ClipRect;

  • 图片和资产Widget:用来管理assets, 显示图片和Icon的一类widget。常用的主要有:

  • Image:用来显示图片的widget;

  • Icon:用来显示Material Design风格icon的widgets;

  • 样式 Widget:用来管理应用的主题,使应用能够响应式的适应屏幕尺寸或添加填充的一类widgets。主要有三个widget:

  • Padding:用来给子widget添加Padding;

  • Theme:为子widget添加主题。主题描述了应用选择的颜色和字体。

  • MediaQuery:建立一个子树,在树中媒体查询解析不同的给定数据。在开发中经常会用到它的MediaQuery.removePadding来移除子widget的padding,MediaQuery.of(context).size 来获取屏幕大小;

如何学习Flutter widgets

Flutter的widgets很多,那么该如何有效的学习这些widgets以及有哪些学习途径呢?

学习策略

  • 首先熟悉上图6大类的widget的作用和应用场景,对widget有个印象;

  • 用widget练习画界面,先实现简单的页面,然后在再到复杂的布局;

  • 实现界面的时候如遇到一些复杂的操作,可以针对性的通过Google查询具体的解决方案;

  • 在实践的过程中多做总结,很多widget的功能都是可以用其他widget来替代的;

  • 不宜将170+个widgets从头到尾一个个记一遍,除非你有特别好的记忆力和时间;

  • 只学习widget的用法却不动手实践,纸上得来终觉浅,绝知此事要躬行;

  • 不宜死记硬背,每个widget都有它特定的应用场景,以及复杂的页面都是由各种各样widget组合而来,这些需要在实践过程中慢慢积累经验;

学习途径

  • 可以在上面搜索任何的widget的介绍和使用说明,部分widget还有视频介绍哦

  • Flutter SDK源码:Flutter sdk中的注释是比较详尽的,遇到陌生的widget通过长按点击去查看源码的注释说明也是个不错的学习方式;

  • 官库的issues中沉淀了很多网友在使用Flutter过程中所遇到的问题以及相应的解决方案,遇到问题时不妨先在上面搜一下,说不定已经有网友踩过坑了;

  • 万能的Google:Flutter从1.0发布到现在已经积累了不小的社区生态,网络也沉淀了很多针对各种各样问题的解决方案;使用widget过程中遇到无法解决的问题,都可以通过Google来检索;

  • 课程问答区:当尝试以上方式都无法解决你的问题的时候,不要忘记课程问答区以及讲师团队在为你保驾护航

4.如何快速上手Flutter布局

目录

  • LinearLayout 在Flutter中等价于什么(Android)?

  • RelativeLayout 在Flutter中等价于什么(Android)?

  • 如何使用widget定义布局属性?

  • 如何分层布局?

  • 如何设置布局样式?

  • ScrollView在Flutter中等价于什么?

  • 谁是Flutter的列表组件?

  • 如何知道点击了列表中哪个item?

  • 如何动态更新ListView?

LinearLayout 在Flutter中等价于什么(Android)?

在Android中,使用LinearLayout来使你的控件呈水平或垂直排列。在Flutter中,你可以使用Row或Column widget来实现相同的结果:

@override  
Widget build(BuildContext context){returnRow( mainAxisAlignment: MainAxisAlignment.center, children:<Widget>[Text('Row One'),Text('Row Two'),Text('Row Three'),Text('Row Four'),],);}代码块123
@override  
Widget build(BuildContext context){returnColumn( mainAxisAlignment: MainAxisAlignment.center, children:<Widget>[Text('Column One'),Text('Column Two'),Text('Column Three'),Text('Column Four'),],);}代码块123
要了解有关构建线性布局的更多信息,可参考区贡献的媒体文章 Flutter For Android Developers : How to design LinearLayout in Flutter?

RelativeLayout 在Flutter中等价于什么(Android)?

RelativeLayout用于使widget相对于彼此位置排列。在Flutter中,有几种方法可以实现相同的结果

您可以通过使用ColumnRowStack的组合来实现RelativeLayout的效果。您可以为widget构造函数指定相对于父组件的布局规则。

推荐参考在StackOverflow上的一个在Flutter中构建RelativeLayout的例子。

如何使用widget定义布局属性?

在Flutter中,布局主要由专门设计用于提供布局的小部件定义,并结合控件widget及其样式属性。

例如, widgets 控制一个数组中的条目 并且 分别垂直和水平对齐它们。 Container widget 控制一个布局的样式和属性, 并且 Center widget 负责居中它的子widget。

// Flutter  Center(  
 child:Column( children:<Widget>[Container( color: Colors.red, width:100.0, height:100.0,),Container( color: Colors.blue, width:100.0, height:100.0,),Container( color: Colors.green, width:100.0, height:100.0,),],),)代码块123

Flutter在其核心widget库中提供了各种布局小部件。 例如, Padding, Align, 和 Stack

更多布局widget可参考 Layout Widgets

如何分层布局?

在Android中,我们可以使用FrameLayout布局进行分层。

Flutter 使用Stack widget 控制子widget在一层。 子widgets可以完全或者部分覆盖基础widgets。

Stack控件将其子项相对于其框的边缘定位。如果您只想重叠多个子窗口小部件,这个类很有用。

// Flutter  
Stack(  
 alignment: const Alignment(0.6, 0.6), children: <Widget>[ CircleAvatar( backgroundImage: NetworkImage( "https://avatars3.githubusercontent.com/u/14101776?v=4"), ), Container( decoration: BoxDecoration( color: Colors.black45, ), child: Text('Flutter'), ), ],)  
代码块123

上一个示例使用 Stack 覆盖容器 (显示其“Text”在半透明的黑色背景上) 在’CircleAvatar之上.Stack偏移文本 使用alignment属性和Alignment`定位。

如何设置布局样式?

Flutter有一套独特的布局系统,PaddingCenterColumnRow、等都是widget,另外组件也通常接受用于布局样式的构造参数:比如Textwidget可以使用TextStyle属性。如果要在多个位置使用相同的文本样式, 你可以创建一个 TextStyle 类并将其应用于各个 Text widgets。

// Flutter  var textStyle =TextStyle(fontSize:32.0, color: Colors.cyan, fontWeight:  
 FontWeight.w600);...Center(  
 child:Column( children:<Widget>[Text('Sample text', style: textStyle,),Padding( padding: EdgeInsets.all(20.0), child:Icon(Icons.lightbulb_outline, size:48.0, color: Colors.redAccent)),],),)代码块1234

ScrollView在Flutter中等价于什么?

在Android中,ScrollView允许您包含一个子控件,以便在用户设备的屏幕比控件内容小的情况下,使它们可以滚动。在Flutter中,最简单的方法是使用ListView。但在Flutter中,一个ListView既是一个ScrollView,也是一个Android ListView。

在 iOS 中,你给 view 包裹上 ScrollView 来允许用户在需要时滚动你的内容。在 Flutter 中,最简单的方法是使用 ListView widget。它表现得既和 iOS 中的 ScrollView 一致,也能和 TableView 一致,因为你可以给它的 widget 做垂直排布:

@override  
Widget build(BuildContext context){returnListView( children:<Widget>[Text('Row One'),Text('Row Two'),Text('Row Three'),Text('Row Four'),],);}代码块123
更多关于在 Flutter 中如何排布 widget 的文档,请参阅 layout tutorial

谁是Flutter的列表组件?

  • 在 iOS 中,通常用 UITableViewUICollectionView 来展示一个列表;

  • 在 Android 中,通常用 ListViewRecyclerView 来展示一个列表;

  • 在 RN 中,通常用 FlatListSectionList 来展示一个列表;

在 Flutter 中,你可以用 ListView 来达到相似的实现:

import'package:flutter/material.dart';voidmain(){runApp(SampleApp());}classSampleAppextendsStatelessWidget{// This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, ), home: SampleAppPage(), ); }}  classSampleAppPageextendsStatefulWidget{SampleAppPage({Key key}):super(key: key);@override _SampleAppPageState createState()=>_SampleAppPageState();}class_SampleAppPageStateextendsState<SampleAppPage>{@override Widget build(BuildContext context){returnScaffold( appBar:AppBar( title:Text("Sample App"),), body:ListView(children:_getListData()),);}_getListData(){ List<Widget> widgets =[];for(int i =0; i <100; i++){ widgets.add(Padding(padding: EdgeInsets.all(10.0), child:Text("Row $i")));}return widgets;}}代码块123456789101112131415
在Android ListView中,您可以创建一个适配器,然后您可以将它传递给ListView,该适配器将使用适配器返回的内容来展示每一行,从上面代码中不难看出,在Flutter中没有adapter的等价物,我们唯一要做的就是控制这个list中要展示的数据。

如何知道点击了列表中哪个item?

import'package:flutter/material.dart';voidmain(){runApp(SampleApp());}classSampleAppextendsStatelessWidget{// This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, ), home: SampleAppPage(), ); }}  classSampleAppPageextendsStatefulWidget{SampleAppPage({Key key}):super(key: key);@override _SampleAppPageState createState()=>_SampleAppPageState();}class_SampleAppPageStateextendsState<SampleAppPage>{@override Widget build(BuildContext context){returnScaffold( appBar:AppBar( title:Text("Sample App"),), body:ListView(children:_getListData()),);}_getListData(){ List<Widget> widgets =[];for(int i =0; i <100; i++){ widgets.add(GestureDetector( child:Padding( padding: EdgeInsets.all(10.0), child:Text("Row $i"),), onTap:(){print('row tapped');},));}return widgets;}}代码块123456789101112131415

在上述代码中我们通过GestureDetector来监听item的点击事件。

如何动态更新ListView?

  • 在 Android 中,改变列表数据后通过notifyDataSetChanged来更新列表;

  • 在 iOS 中,你改变列表的数据,并通过 reloadData() 方法来通知 table 或是 collection view;

在 Flutter 中,如果你想通过 setState() 方法来更新 widget 列表,你会很快发现你的数据展示并没有变化。这是因为当 setState() 被调用时,Flutter 渲染引擎会去检查 widget 树来查看是否有什么地方被改变了。当它得到你的 ListView 时,它会使用一个==判断,并且发现两个 ListView 是相同的。没有什么东西是变了的,因此更新不是必须的。

一个更新 ListView 的简单方法是,在setState() 中创建一个新的 List,并把旧 List 的数据拷贝给新的 list。虽然这样很简单,但当数据集很大时,并不推荐这样做,来一起看个demo:

import'package:flutter/material.dart';voidmain(){runApp(SampleApp());}classSampleAppextendsStatelessWidget{// This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, ), home: SampleAppPage(), ); }}  classSampleAppPageextendsStatefulWidget{SampleAppPage({Key key}):super(key: key);@override _SampleAppPageState createState()=>_SampleAppPageState();}class_SampleAppPageStateextendsState<SampleAppPage>{  
 List widgets =[];@overridevoidinitState(){super.initState();for(int i =0; i <100; i++){ widgets.add(getRow(i));}}@override Widget build(BuildContext context){returnScaffold( appBar:AppBar( title:Text("Sample App"),), body:ListView(children: widgets),);}  
 Widget getRow(int i){returnGestureDetector( child:Padding( padding: EdgeInsets.all(10.0), child:Text("Row $i"),), onTap:(){setState((){ widgets = List.from(widgets); widgets.add(getRow(widgets.length +1));print('row $i');});},);}}代码块1234567891011121314151617

一个推荐的、高效的且有效的做法是,使用 ListView.Builder 来构建列表。这个方法在你想要构建动态列表,或是列表拥有大量数据时会非常好用:

import'package:flutter/material.dart';voidmain(){runApp(SampleApp());}classSampleAppextendsStatelessWidget{// This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, ), home: SampleAppPage(), ); }}  classSampleAppPageextendsStatefulWidget{SampleAppPage({Key key}):super(key: key);@override _SampleAppPageState createState()=>_SampleAppPageState();}class_SampleAppPageStateextendsState<SampleAppPage>{  
 List widgets =[];@overridevoidinitState(){super.initState();for(int i =0; i <100; i++){ widgets.add(getRow(i));}}@override Widget build(BuildContext context){returnScaffold( appBar:AppBar( title:Text("Sample App"),), body: ListView.builder( itemCount: widgets.length, itemBuilder:(BuildContext context, int position){returngetRow(position);},),);}  
 Widget getRow(int i){returnGestureDetector( child:Padding( padding: EdgeInsets.all(10.0), child:Text("Row $i"),), onTap:(){setState((){ widgets.add(getRow(widgets.length +1));print('row $i');});},);}}代码块1234567891011121314151617

与创建一个 “ListView” 不同,创建一个 ListView.builder 接受两个主要参数:列表的初始长度,和一个 ItemBuilder 方法。

ItemBuilder 方法和 iOS的cellForItemAt 代理方法非常类似,它接受一个位置,并且返回在这个位置上你希望渲染的 cell。

最后,也是最重要的,注意 onTap() 函数里并没有重新创建一个 List,而是 add 了一个 widget。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
通过本课程学习您可以学习到Dart语言如下知识:第1章 Dart语言概述:Dart语言简介、Dart语言支持平台开发、Flutter为什么选择Dart语言。第2章 开发环境搭建:下载Dart SDK、Windows下安装Dart SDK、macOS下安装Dart SDK、Visual Studio Code开发工具、IntelliJ IDEA开发工具。第3章 完成个Dart程序:动动手写一个HelloWorld、Dart源代码文件组织结构、Visual Studio Code调试Dart代码、IntelliJ IDEA调试Dart代码。第4章 Dart语法基础:标识符、关键字、变量、常量、注释、库。第5章 Dart数据类型:数值类型、字符串、数据类型相互转换、布尔类型和枚举类型第6章 运算符:算术运算符、算术赋值运算符、关系运算符、逻辑运算符、位运算符、条件运算符、类型检查运算符。第7章 控制语句:分支语句、循环语句、跳转语句。第8章 函数:函数声明、可选参数、头等函数(first-class function)、匿名函数。第9章 类:类声明、getter和setter访问器、构造函数、静态变量和静态方法、级联符号。第10章 继承与多态:Dart中的继承实现、调用父类构造函数、成员变量的覆盖(Override)、方法的覆盖(Override)、多态、混入(Mixins)。第11章 抽象类与接口:抽象类、接口、Dart中隐式接口、实现接口。第12章 数据容器:List容器、Set容器、Map容器、泛型。第13章 异常处理:捕获异常、try-on捕获异常、try-catch捕获异常、try-on-catch捕获异常、使用finally代码块、手动抛出异常、自定义异常类。第14章 异步编程:Dart异步处理机制、案例:同步函数实现读取文件、案例:异步函数实现读取文件、Future对象。  

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值