主流框架对比
- Cordova:Cordova基于网页技术进行包装,利用插件的形式开发移动应用的,这点的性能和体验,Flutter完胜
- RN(React Native):RN的效率是由于将View编译成原生View,效率上比Cordova的HTML5高很多,但它也有效率问题:RN的渲染机制是基于前端框架的考虑,复杂UI的渲染需要依赖多个View叠加。比如渲染个复杂的ListView,每个小控件都是个native的View,然后相互组合叠加,若此时我们滑动刷新则会有很多个对象需要渲染,也就是说RN的列表方案不友好。
- Flutter:吸收了前两者的教训,在渲染技术上选择自己实现(GDI),有更好的可控性,使用了新语言Dart,避免了RN那种通过桥接器JavaScript通讯导致效率底下的问题,故在性能方面比RN高。另外,打开Android手机开发者选项里的显示边界布局,可以发现Flutter的布局是一个整体,说明Flutter的渲染没有使用原生控件。
Flutter采用GPU渲染技术,性能更高,其编写的应用可以达到120fps(每秒传输帧数),完全可以胜任游戏的制作。RN的性能只能达到60fps。
Flutter环境安装
安装jdk、配置jdk环境变量
下载Flutter SDK、flutter环境变量配置(可以在终端直接使用flutter命令)
开发工具:Android Studio 或 VS Code
flutter sdk下flutter_console.bat
双击运行并启动flutter命令行。就可以在Flutter命令行运行flutter命令了。
进行Flutter doctor的测试
在终端中输入 flutter doctor
进行检测
出现
X Android SDK is missing command line tools;...
需要安装Android Studio
AS(Android Studio)配置Flutter插件:File–Settings–Plugin搜索Flutter,点击安装,重启
再打开终端,输入
flutter doctor --android-licenses
,安装Android证书
安装AVD虚拟机
- 现在需要一个虚拟机来运行我们的程序,可以点击Android Studio中的上方菜单
tool
-AVD Manager
选项。 - 出现新建菜单,选择
Create Virtual Device.....
,如果你一个虚拟机也没建过,这个选项在对话框的中间(我一定跟我的图一样)。 - 选择虚拟机类型,这个你随意选就好,我选择的是
Nexus 5x
。(如果你屏幕小,就选择一个小屏幕的虚拟机) - 选择系统,这里尽量选择最新的,我选择了
Android 9.0
系统,选择好后,又是一个漫长的等待过程。 - 安装好后,点击开始按钮,运行虚拟机了(第一次运行,需要安装系统,会慢一些)。
若是直接用真机的话可以不用安装AVD虚拟机
使用Android Studio开发Flutter
使用VSCode开发Flutter
在终端运行
flutter doctor
,查看输出是否有问题或在VS Code的命令面板找到Flutter:
Run Flutter Doctor
,执行VSCode命令面板(cmd+shift+p)支持搜索,输入flutter搜索我们需要的命令
新建Flutter项目
- 在终端输入
flutter create
- 或在VSCode命令面板,找到
Flutter :New Project
执行
VSCode运行Flutter项目
在VSCode的终端输入flutter run
运行Flutter项目
- 调试->启用调试(F5)
可以在命令面板送找到
Debug:Select and Start Debugging
执行->选择添加配置->选择Dart&Flutter
,这样就不用每次都选调试环境了。 也可以在调试界面 选择小齿轮 选择Dart&Flutter
hot reload
- save(cmd+s)
- 或者点击绿色圆形箭头按钮
选择调试设备
在界面右下角可以选择设备
或者命令面板 找到
Flutter: Select Devices
视图调试
在运行flutter的时候打开命令面板输入 Flutter:Toggle
即可看到熟悉的命令
- Toggle Baseline Painting
- Toggle Repaint Rainbow
- Toggle Slow Animations
- Toggle Slow-Mode Banner
Observatory
命令面板 Dart: Open Observatory
调试控制台
很多时候VSCode开发体验都蛮好的,但是调试控制台真的难用,还不支持搜索。 不过我们可以设置flutter log输出文件,用其他软件来看log。
在用户设置中搜索 flutter run log 中设置
用其他软件打开这个文件 比如自带的控制台
open -a Console .vscode/run.log
Assists & Quick Fixes
- 命令面板
Quick fix
或者快速修复
(没错支持中文输入=。=) - 或者使用快捷键cmd + .
Sort Members
- 命令面板
Sort Members
- 或者 右键->源代码操作->Sort Members
- 也可以自定义
Sort Members
的快捷键
Organize Imports
- 命令面板
Organize Imports
- 或者 右键->源代码操作->Organize Imports
- 或者 快捷键shift + option + o
格式化(Fotmat Document)
- 命令面板
Fotmat Document
- 或者 右键->设置文档的格式
- 或者 快捷键 shift + option + f
Go to Definition
- 右键
转到定义
- 快捷键f12 或者 cmd+左键
Find All References
- 右键
Find All References
代码片段
Flutter扩展包含了一些常用的代码片段
stless
StatelessWidgetstfull
StatefulWidgetstanim
StatefulWidget with AnimationController
我们也可以增加自己自定义的代码片段
- 在控制台输入
Configure User Snippets
/ 首选项:配置用户代码片段 - 选择
dart.json
- 编写自己的代码片段
Flutter打包
生成keystore
VSCode
终端:keytool -genkey -v -keystore ~/key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key
其中
~/key.jks
要改成我们自己的盘,比如e:\key.jks
flutter doctor -v
这个命令可以找到
keytool.exe
位置
新建key.properties
在android根目录下新建key.properties
,内容:
storePassword=123123
keyPassword=123123
keyAlias=key
storeFile=E:/key.jks
在app/build.gradle
下配置这个签名文件
在android{
这行前面加上
def keystorePropertiesFile = rootProject.file("key.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
把如下代码进行替换
buildTypes {
release {
signingConfig signingConfigs.debug
}
}
替换成的代码:
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
生成apk
直接在终端中输入:
flutter build apk
这时候就打包成功了,剩下的安装过程我就省略
基础
Flutter:包含Flutter的引擎、框架、Widget、工具和Dart SDK
Material 是一种标准的移动端和 web 端的视觉设计语言。
main 函数使用了
=>
符号,这是 Dart 中单行函数或方法的简写MyApp
该应用程序继承了StatelessWidget
,这将会使应用本身也成为一个Widget
。在Flutter
中,大多数东西都是widget
,包括对齐alignment
、填充padding
、布局layout
main 调用的
MyApp
中要有MaterialApp
,否则会报错。在
MaterialApp
中可以设置主题,控制应用程序的外观和风格在
MaterialApp
中至少要创建一个home
或routes
或onGenerateRoute
或builder
Scaffold
是Material library
中提供的一个widget
,它提供了默认的导航栏,标题和包含主屏幕 widget树(可以很复杂)的 body 属性。StatefulWidget
有状态的部件持有的状态可能在
Widget
生命周期中发生变化,实现一个 stateful widget 至少需要两个类:StatefulWidget
类、State
类。StatefulWidget
类本身是不变的,但是State
类在widget
生命周期中始终存在widget
主要工作是提供一个build()
方法来描述如何根据其他较低级别的widget
来显示自己。ThemeData
属性及描述属性名 类型 说明 accentColor
Color
前景色(文本、按钮等) accentColorBrightness
Brightness
``accentColor 的亮度。用于确定放置在突出颜色顶部的文本和图标的颜色(例如
FloatingButton`上的图标)accentIconTheme
IconThemeData
与突出颜色对照的图片主题 accentTextTheme
TextTheme
与突出颜色对照的文本主题 backgroundColor
Color
与 primaryColor
对比的颜色(例如:用作进度条的剩余部分)bottomAppBarColor
Color
BottomAppBar
的默认颜色brightness
Brightness
应用程序整体主题的亮度。由按钮等 Widget
使用buttonColor
Color
Material
中RaisedButtons
使用的默认填充色ButtonTheme
ButtonThemeData
定义了按钮等空间的默认配置,如 RaisedButton
和FlatButton
canvasColor
Color
MaterialType.canvas Material
的默认颜色chipTheme
ChiipThemeData
用于渲染 Chip
的颜色和样式dialogBackgroundColor
Color
Dialog
原色的背景色disabledColor
Color
用于 Widget
无效的颜色,包括任何状态。例如禁用复选框dividerColor
Color
Dividers
和PopupMenuDividers
的颜色。也用于ListTiles
中间和DataTables
的每行中间errorColor
Color
用于输入验证错误的颜色。例如在 TextField
中hashCode
int
对象的哈希值 highlightColor
Color
用于类似墨水喷溅动画或指示菜单被选中的高亮颜色 iconTheme
IconThemeData
与卡片和画布颜色形成对比的图标主题 indicatorColor
Color
TabBar
中选项选中的指示器颜色inputDecorationTheme
InpputDecorationTheme
InputDecorator
、TextField
和TextFormField
的默认InputDecoration
值基于此主题platform
TargetPlatform
Widget
需要适配的目标类型primaryColor
Color
App
主要部分的背景色(ToolBar
、tabbar
等)primaryColorBrightness
Brightness
primaryColor
的亮度primaryColorDark
Color
primaryColor
的较暗版本primaryColorLight
Color
primaryColor
的较亮版本primaryIconTheme
IconThemeData
一个与主色对比的图片主题 primaryTextTheme
TextThemeData
一个与主色对比的文本主题 scaffoldBackgroundColor
Color
作为 Scaffold 基础的 Material 默认颜色,典型 Material 应用或应用内页面的背景颜色 secondaryHeaderColor
Color
有选定行时 PaginatedDataTable
标题的颜色selectedRowColor
Color
选中行时的高亮颜色 sliderTheme
SliderThemeData
用于渲染 Slider
的颜色和形状splashColor
Color
墨水喷溅的颜色 splashFactory
InteractiveFeatureFactory
定义 InkWall
和InkResponse
生成的墨水喷溅的外观textSelectionColor
Color
文本字段中选中文本的颜色。例如 TextField
textSelectionHandleColor
Color
用于调整当前文本的哪个部分的句柄颜色 textTheme
TextTheme
与卡片和画布对比的文本颜色 toggleableActiveColor
Color
用于突出显示切换 Widget
(如Switch
、Radio
和Checkbox
)的活动状态的颜色unselectedWidgetColor
Color
用于 Widget
处于非活动(但已启用)状态的颜色。例如,未选中的复选框。通常与accentColor
形成对比runtimeType
Type
表示对象的运行时类型
局部主题:创建特有的主题数据或扩展父主题。
创建特有的主题数据
new Theme( //创建一个特有的主题数据 data:new ThemeData( accentColor: Colors.yellow, ), child: new FloatingActionButton( onPressed:(){}, child:new Icon(Icons.add), ), );
扩展父主题(无须覆盖所有的主题属性,用 copyWith)
new Theme( //覆盖 accentColor 为 Colors.yellow data: Theme.of(context).copyWith(accentColor: Colors.yellow), child: new FloatingActionButton( onPressed: null, child: new Icon(Icons.add), ), );
Theme.of(context)
可通过上下文获取主题,查找最近的主题,若找不到就会找整个应用的主题。第三方库如:网络请求(http)、自定义导航/路由处理(fluro)、集成设备 API(如 url_launcher&battery)以及第三方平台SDK(如 Firebase)等
关键字(56个):abstract、do、import、super、as、dynamic、in、switch、assert、else、interface、sync、enum、implement、is、this、async、export、library、throw、await、external、mixin、true、break、extends、new、try、case、factory、null、typedef、catch、false、operator、var、class、final、part、void、const、finally、rethrow、while、continue、for、return、with、covariant、get、set、yield*、default、if、static、deferred
Dart 语言常用库(使用频率最高
dart:core
、dart:html
、dart:io
)包名 描述 dart:async
异步编程支持,提供 Future 和 Stream 类 dart:collection
对 dart:core 提供更多的集合支持 dart:convert
不同类型(JSON,UTF-8)间的字符编码、解码支持 dart:core
Dart 语言内建的类型、对象以及 dart 语言核心的功能 dart:html
网页开发用到的库 dart:io
文件读写 I/O 相关操作的库 dart:math
数字常量及函数,提供随机数算法 dart:svg
事件和动画的矢量图像支持 final和const的区别
final wordPair = WordPair.random();
final表明这个变量不能再发生更改,但初始值在编译期是不确定的,在运行时赋值后就不能再更改了。
const city = "烟台";
const定义时需要是个明确的值,在编译时就知道值了。
符号
=>
Dart中单行函数或方法的简写
??
Dart中表示 if null
//如果b为null则a=hello,否则a=b
String a = b ?? 'hello'
Widget
Flutter中大多数是widget,包含对齐(alignment)、填充(padding)和布局(layout)
widget的主要工作是提供一个build()方法来描述如何根据其他较低级别的widget来显示自己Stateless widgets
是不可变的, 这意味着它们的属性不能改变 - 所有的值都是最终(final)的.Stateful widgets
持有的状态可能在widget生命周期中发生变化. 实现一个 stateful widget 至少需要两个类:
- 一个
StatefulWidget
类。 - 一个
State
类。StatefulWidget
类本身是不变的,但是 State类在widget生命周期中始终存在。
pubspec
pubspec文件管理Flutter应用程序的assets(资源,如图片、package等)
架构设计

Framework
一个纯 Dart实现的 SDK,类似于 React在 JavaScript中的作用。它实现了一套基础库, 用于处理动画、绘图和手势。并且基于绘图封装了一套 UI组件库,然后根据 Material 和Cupertino两种视觉风格区分开来。这个纯 Dart实现的 SDK被封装为了一个叫作 dart:ui
的 Dart库。我们在使用 Flutter写 App的时候,直接导入这个库即可使用组件等功能。
Engine
一个纯 C++实现的 SDK,其中囊括了 Skia
引擎、Dart运行时、文字排版引擎等。不过说白了,它就是 Dart的一个运行时,它可以以JIT
、JIT Snapshot
或者 AOT
的模式运行 Dart
代码。在代码调用 dart:ui
库时,提供 dart:ui
库中 Native Binding
实现。 不过别忘了,这个运行时还控制着 VSync
信号的传递、GPU数据的填充等,并且还负责把客户端的事件传递到运行时中的代码。
网络
Dio
是Flutter下热门的网络请求框架之一
JSPang13 个 demos
void main()=>runApp(MyApp());
其中 main()是主函数,是程序的入口
flutter 1.0 后就可以省略 new
要调用其他dart 文件的 class 需要在调用的类中加
import ‘文件路径’
;Scaffold是页面脚手架
list..add(widget 实例)..add(widget 实例);
可以使用..
来给集合连续添加元素StatefulWidget
要调用setState(){}
才可以更新内容BottomNavigationBarItem
是底部导航栏FloatingActionButton
是浮动的按钮Navigator
页面跳转push
,跳转后返回的回调pop
页面跳转加动画,派生出
PageRouteBuilder
在其构造方法中加动画毛玻璃效果:写个约束盒子组件
ConstrainedBox
(放图),再写个可裁切的矩形ClipRect
覆盖在上方(在背景过滤器BackdropFilter
中加半透明、宽高、装饰器BoxDeration
等)上部的导航栏:在
AppBar
中添加多个 Tab 组件页面状态切换后保持住:派生出
PageState
加with AutomaticKeepAliveClientMixin
,重写bool get wantKeepAlive=>true;
搜索条:
onpress
中加 showSearch(context:context, delegate:派生 SearchDelegate());会开启一个新页面派生
SearchDelegate
中buildActions
右侧icon
、buildLeading
左侧icon
、buildResults
搜索结果、buildSuggestions
搜索建议Wrap流式布局
展开闭合
ExpansionTile
、列表带展开闭合ExpansionPanelList
画曲线:
ClipPath
内 clipper:派生CustomClipper<Path>
,贝塞尔曲线要确定4 个范围点+控制点+结束点。可以画多条曲线闪屏动画:派生 State,自定义
AnimationController
用来控制时长、动画播放。Animation 用来设置动画并加 status 监听,结束就跳转右滑返回:页面导入
cupertino.dart
而不是material.dart
,用CupertinoPageScaffold
脚手架+CupertinoButton
+CupertinoPageRoute
轻量级提示:
Tooltip
(长按的时候会有提示)拖拽效果:自定义个
DraggableWidget extends StatefulWidget
Positioned
页面脚手架中Draggable
(feedback 拖动控件的时候子元素的样式、onDraggableCanceled
松手的时候)。外面调用这个自定义的DraggableWidget
传不同的值即可
代码
去除右上角“Debug”字样
在(SatelessWidget)MyApp的build的return中 添加 //去除右上角的debug字样 debugShowCheckedModeBanner: false,
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context){
return new MaterialApp(
...
//去除右上角的debug字样
debugShowCheckdModeBanner: false,
...
);
}
}
flutter内置了10多种show
showDialog
常用的提示弹窗(带标题、提示内容、取消按钮、确认按钮)
showDialog(
context: context,
builder: (context) {
return AlertDialog(
...
);
}
);
关闭对话框需要使用
Navigator.of(context, rootNavigator: true).pop(result)
而不是
Navigator.pop(context, result)
showCupertinoDialog
ios风格的提示弹窗(带标题、提示内容、取消按钮、确认按钮)
showCupertinoDialog(
context: context,
builder: (context) {
return CupertinoAlertDialog(
...
);
});
builder
通常返回 CupertinoDialog
或者 CupertinoAlertDialog
showGeneralDialog
自定义弹窗
showGeneralDialog(
context: context,
barrierDismissible:true,
barrierLabel: '',
transitionDuration: Duration(milliseconds: 200),
pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return Center(
child: Container(
height: 300,
width: 250,
color: Colors.lightGreenAccent,
),
);
});
barrierDismissible
:是否可以点击背景关闭。
barrierColor
:背景颜色
transitionDuration
:动画时长,
transitionBuilder
是构建进出动画,默认动画是渐隐渐显,构建缩放动画代码如下:
showGeneralDialog(
transitionBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return ScaleTransition(scale: animation, child: child);
},
...
)
showAboutDialog
AboutDialog用于描述当前App信息,底部提供2个按钮:查看许可按钮和关闭按钮。AboutDialog需要和showAboutDialog配合使用,用法如下:
showAboutDialog(
context: context,
applicationIcon: Image.asset(
'images/bird.png',
height: 100,
width: 100,
),
applicationName: '应用程序',
applicationVersion: '1.0.0',
applicationLegalese: 'copyright 老孟,一枚有态度的程序员',
children: <Widget>[
Container(
height: 30,
color: Colors.red,
),
Container(
height: 30,
color: Colors.blue,
),
Container(
height: 30,
color: Colors.green,
)
],
);
属性说明如下:
applicationIcon
:应用程序的图标。applicationName
:应用程序名称。applicationVersion
:应用程序版本。applicationLegalese
:著作权(copyright)的提示。children
:位置如上图的红蓝绿色的位置。
所有的属性都需要手动设置,不是自动获取的。
下面的2个按钮根据应用程序支持的语言显示相应的语言,比如显示中文方法如下:
- 在
pubspec.yaml
中配置支持国际化:
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
- 在MaterialApp中配置当前区域:
MaterialApp(
title: 'Flutter Demo',
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('zh', 'CH'),
const Locale('en', 'US'),
],
locale: Locale('zh'),
...
)复制代码
showLicensePage
此控件基本不会用到,浏览一下即可。
LicensePage用于描述当前App许可信息,LicensePage需要和showLicensePage配合使用,用法如下:
showLicensePage(
context: context,
applicationIcon: Image.asset(
'images/bird.png',
height: 100,
width: 100,
),
applicationName: '应用程序',
applicationVersion: '1.0.0',
applicationLegalese: 'copyright 老孟,一枚有态度的程序员',
);
页面中下面的英文我们是无法更改的
showBottomSheet
在最近的Scaffold
父组件上展示一个material风格的bottom sheet,位置同Scaffold
组件的bottomSheet
,如果Scaffold
设置了bottomSheet
,调用showBottomSheet抛出异常。
基本用法如下:
showBottomSheet(
context: context,
builder: (context) {
return Container(height: 200, color: Colors.lightBlue);
});
设置其背景颜色、阴影值、形状:
showBottomSheet(
context: context,
backgroundColor: Colors.lightGreenAccent,
elevation:20,
shape: CircleBorder(),
builder: (context) {
return Container(height: 200);
});
showModalBottomSheet
从底部弹出,通常和BottomSheet配合使用,用法如下:
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return BottomSheet(...);
});
设置背景、阴影、形状:
showModalBottomSheet(
context: context,
backgroundColor: Colors.lightBlue,
elevation: 10,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
...
)
isDismissible
:是否可以点击背景关闭。
isScrollControlled
参数指定是否使用可拖动的可滚动的组件,如果子组件是ListView或者GridView,此参数应该设置为true,设置为true后,最大高度可以占满全屏。用法如下:
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (BuildContext context) {
return ListView.builder(
itemBuilder: (context, index) {
return ListTile(
title: Text('老孟$index'),
);
},
itemExtent: 50,
itemCount: 50,
);
});复制代码
showCupertinoModalPopup
showCupertinoModalPopup 展示ios的风格弹出框,通常情况下和CupertinoActionSheet配合使用,用法如下:
showCupertinoModalPopup(
context: context,
builder: (BuildContext context) {
return CupertinoActionSheet(
title: Text('提示'),
message: Text('是否要删除当前项?'),
actions: <Widget>[
CupertinoActionSheetAction(
child: Text('删除'),
onPressed: () {},
isDefaultAction: true,
),
CupertinoActionSheetAction(
child: Text('暂时不删'),
onPressed: () {},
isDestructiveAction: true,
),
],
);
}
);
filter
参数可以对弹出框以外的区域做模糊或者矩阵操作,用法如下:
showCupertinoModalPopup(
context: context,
filter: ImageFilter.blur(sigmaX: 5.0, sigmaY: 5.0),
...
)
弹出框以外的区域有毛玻璃的效果。
showMenu
showMenu弹出一个Menu菜单,用法如下:
showMenu(
context: context,
position: RelativeRect.fill,
items: <PopupMenuEntry>[
PopupMenuItem(child: Text('语文')),
PopupMenuDivider(),
CheckedPopupMenuItem(
child: Text('数学'),
checked: true,
),
PopupMenuDivider(),
PopupMenuItem(child: Text('英语')),
]);复制代码
position
参数表示弹出的位置
弹出的位置在屏幕的左上角,我们希望弹出的位置在点击按钮的位置,因此需要计算按钮的位置,计算如下:
final RenderBox button = context.findRenderObject();
final RenderBox overlay = Overlay.of(context).context.findRenderObject();
final RelativeRect position = RelativeRect.fromRect(
Rect.fromPoints(
button.localToGlobal(Offset(0, 0), ancestor: overlay),
button.localToGlobal(button.size.bottomRight(Offset.zero),
ancestor: overlay),
),
Offset.zero & overlay.size,
);复制代码
你需要将按钮单独封装为StatefulWidget组件,否则context代表的就不是按钮组件。
showSearch
showSearch 是直接跳转到搜索页面,用法如下:
showSearch(context: context, delegate: CustomSearchDelegate());
class CustomSearchDelegate extends SearchDelegate<String>{
@override
List<Widget> buildActions(BuildContext context) {
return null;
}
@override
Widget buildLeading(BuildContext context) {
return null;
}
@override
Widget buildResults(BuildContext context) {
return null;
}
@override
Widget buildSuggestions(BuildContext context) {
return null;
}
}复制代码
使用showSearch,首先需要重写一个SearchDelegate,实现其中的4个方法。
buildLeading
表示构建搜索框前面的控件,一般是一个返回按钮,点击退出,代码如下:
@override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: Icon(Icons.arrow_back,color: Colors.blue,),
onPressed: (){
close(context, '');
},
);
}
buildSuggestions
是用户正在输入时显示的控件,输入框放生变化时回调此方法,通常返回一个ListView,点击其中一项时,将当前项的内容填充到输入框,用法如下:
@override
Widget buildSuggestions(BuildContext context) {
return ListView.separated(
itemBuilder: (context, index) {
return ListTile(
title: Text('老孟 $index'),
onTap: () {
query = '老孟 $index';
},
);
},
separatorBuilder: (context, index) {
return Divider();
},
itemCount: Random().nextInt(5),
);
}
buildActions
输入框后面的控件,一般情况下,输入框不为空,显示一个清空按钮,点击清空输入框:
@override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: Icon(
Icons.clear,
),
onPressed: () {
query = '';
},
)
];
}复制代码
buildResults
是构建搜索结果控件,当用户点击软键盘上的“Search”时回调此方法,一般返回ListView,用法如下:
@override
Widget buildResults(BuildContext context) {
return ListView.separated(
itemBuilder: (context, index) {
return Container(
height: 60,
alignment: Alignment.center,
child: Text(
'$index',
style: TextStyle(fontSize: 20),
),
);
},
separatorBuilder: (context, index) {
return Divider();
},
itemCount: 10,
);
}