s)
1系统要求
2 设置Flutter镜像(非必须)
3获取Flutter SDK
4Android 开发环境设置
5 安装Flutter插件(Flutter Dart)
#系统要求
在windows上安装并运行Flutter要满足以下最低要求
1 操作系统:Windows 7 SP1或更新版本
2 操作空间:400MB(Android Studio的磁盘空间)
3工具:Flutter 依赖下面命令行工具
(1)Windows PowerShell 5.0
Windows 10 已经预装了这个工具
(2)Git for Windows 2.x
确保windows电脑下载安装了git工具
镜像
可以从Flutter官网上获取最新的镜像 https://flutter.dev/community/china
(Using Flutter in China)
将以下环境变量加到用户环境变量中:
当前提供的镜像地址
FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
PUB_HOSTED_URL=https://pub.flutter-io.cn
配置环境变量
1 windows
就像平常配置环境变量一样
2mac和linux就比较好配置了
打开(或创建) $HOME/.bash_profile.
文件路径和文件名可能在您的机器上不同:比如博主mac配置的/Users/xxx/.bash_profile
添加以下配置
添加以下配置
#flutter国内用户镜像环境
export
PUB_HOSTED_URL=https://pub.flutter-io.cn
export
FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
保存,使这个.base_profile生效
source 路径/.bash_profile
到此就配置完毕了,如果配置后不能访问,重启以下机器应该就可以了
二 AndroidStuido开发工具相关
1 切换到Android模式下
(1)
(2)
2 环境问题 ,工具问题 ,版本问题
>>Flutter
1 Flutter 环境变量
2 stable,beta, dev, master 建议使用stable
稳定版
3 Flutter doctor 遇到问题可以在cmd中运行这个命令进行诊断
,进而修复
>>工具 AndroidStudio
1 配置 Sdk
2 Flutter Sdk
3 Flutter,Dart 插件
三 Flutter 快速上手开发
程序的入口
Dart 中每一个app 都有一个顶级的 main() 函数
作为应用程序的入口
//Dart
main(){
}
>>>>>>>在先dart编译工具
https://dartpad.dartlang.org/
变量
Dart是类型安全的 -
它使用静态类型检查和运行时的组合,检查以确保变量的值始终与变量的静态值匹配类型。尽量类型是必须的,但某些类型注释是可选的,因为Dart会执行类型推断
#创建和分配 变量
JavaScript中无法定义变量类型。
例:
var name
='JavaScript';
在Dart中,变量必须是明确的
类型或系统能够解析的类型
例:
String name
=“dart”;
var otherName
= 'Dart';
默认值
在JavaScript中,未初始化的变量是undefined
在Dart中,未初始化的变量的初始值为null
注意: 数字在Dart 中
也被当成对象,所以只要带数字类型的未初始化的变量值都是“null'
例:
//JavaScript
var name ;
// == undefined
//Dart
var name ; //
== null
int x;
// == null
检查null 或 零
在javaScript 中 ,1 或者任何非null对象的值被视为true
在Dart中,只有布尔值的值”true“ 被视为true
从Dart 1.12开始 ,null-aware
运算符可帮助我们做null检查
”?.“ 运算符在左边为null的时候会阻断右边的调用
”??“ 运算符 主要是判断左边表达式如果未null 为其赋一个默认值
为右边的值,否则是左边的值
Functions
Dart 和JavaScript的函数类似 。主要区别是声明:
//javascript
function fn(){
return true;
}
//dart
fn(){
return ture;
}
#异步编程
Futures
Dart 中使用 Future来表示异步操作
在Dart 中,async函数返回一个Future,函数的主题是稍候执行 ,await
运算符用于等待Future:
声明式UI
Flutter 采用了声明性UI布局方式
Flutter 入门基础知识
如何使用Widget并将其嵌套以形成widget树?
在Flutter中,几乎所有的东西都是widget
widget是用户界面的基本构建块,您将widget组成一个层次结构,调用widget树,每个窗口widget都是嵌套在父窗口widget中,并从其父窗口继承属性,甚至应用程序对象本身也是一个组件,没有单独的“应用程序”对象。相反,根widget担任此角色
widget可以定义
~ 结构元素-如按钮或者菜单
~文本元素 - 像字体或颜色主题
~类似布局的填充或对齐的一个方向
Flutter
目录结构
图片的声明
Assets 可以被放置到任何属性文件夹中--Flutter
并没有预先定义的文件结构。我们需要在pubspec.yaml 文件中声明assets位置,然后Flutter
会把他们识别出来
举个例子,好吧
icon.png图片放到Flutter工程中,把图片(1.0x)放置到images文件夹中,并把其他分辨率的图片放在对应的文件夹中,并接上合适的比例系数:
images/icon.png
//base : 1.0x image
images/2.0x/icon.png //2.0x
image
images/3.0x/icon.png //3.0x image
接下来就可以在pubspec.yaml
文件中这样声明这个图片资源:
---> assets:
- images/icon.png
---> 现在,我们就可以借助AssetImage来访问它了
return
AssetImage('image/icon.png')
---> 也可以通过 Image Widget
直接使用
@override
Widget build(BuildContext
context){
return
Image.asset('images/icon.png')
}
如何归档Strings资源,以及如何处理不同语言
Flutter 目前没有专门的
字符串资源系统,目前最佳做法是将Strings资源作为静态字段保存在类中 。例如:
class Strings {
static String
welcomeMessage ='welcome to Flutter';
}
然后像如下方式访问它:
Text(Strings.welcomeMessage)
默认情况下,Flutter只支持美式英语字符串
。如果你要支持其他语言,请引入flutter_localizations
包。
你可能也要引入 intl包支持其他 i10n 机制,如果日期/时间格式化
dependencies:
#...
flutter_localizations
sdks:flutter
intl:
'^0.15.6
要使用flutter_localizations
包,还需要在app widget 中指定 localizationsDelegates 和 supportedLocales
。
如何添加Flutter项目所需的依赖?
Flutter
使用Dart构建系统和pub包管理器来处理依赖。这些工具将Android和ios
native包装应用程序的构建委派给相应的构建系统
dependencies:
flutter:
sdk:
flutter
google_sign_in:^3.0.3
注意:在Flutter
中,虽然在Flutter项目中的Android文件夹下有Gradle文件,但只有在添加平台相关所需的依赖关系时才使用这些文件。否则,应该使用pubspec.yaml来声明用于Flutter的外部依赖项
ios也也是一样,如果你的Flutter工程中的ios文件夹中有podfile,请仅在添加ios平台相关的依赖时使用它,否则,应该使用pubspec.yaml来声明用于Flutter的外部依赖项
>>>>>>>>Flutter中查找Flutter插件的一个软件Pub
site (https://pub.dev/flutter)
谁是Flutter中的view
在Flutter中我们可以将widget当作Android ios
,RN中的view,但他们并不完全等价,但当我们试图去理解Flutter是如何工作的时候,我们可以认为他是“声明和构建UI的方式”。
但是,widget和view 有一些区别:
首先widget具有不同的生命周期:他们时不可变的,他们会存在于状态改变之前,每当widget或其他状态发生变化的时,Flutter的框架都会创建一个新的widget
是实例树。相比之下,Android/ios 视图被绘制一次,并且在调用
invalidate/setNeedDisplay之前不会重绘
此外,与view不同,Flutter的widget很轻巧,部分原因在于他的不变性,因为它本身不是视图,并且不会直接绘制任何东西,而是对ui及语义的描述
如何更新widgets
在flutter中,widget不可变的,不会直接更新。相反,我们可以通过操作widget的状态更新他们
。这就是有状态无状态widget的来源 。
statelessWidget
无状态,statefulWidget有状态
无状态widget和有状态的widget之前的区别在与statefulwidgets具有一个state对象,该对象存储状态数据并将其传递到树重建中,因此状态不会丢失
请记住以下规则:如果widget在build之外更改(例如,由于运行时用户交互),则他是有状态的。如果widget永远不会改变,一旦构建,它就是无状态的。但是,即使widget是有状态的,如果包含其他的父窗口小部件本身不对这些更改(或其他输入)做出反应,父widget仍然可以是无状态的
如何声明布局
在flutter中,我们通过编写一个widget树来声明布局
如何在布局中添加或删除组件
在flutter中可以通过动态的返回一个函数表达式,该函数或表达式返回一个widget给父项,并通过布尔值控制该widget的创建
如何对widget做动画
在Flutter
中使用动画库来包裹Widget,而不是创建一个动画widget
在Flutter 中,使用AnimationController,这是一个可以暂替、寻找、停止、反转的Animation类型。它需要一个Ticker当vsync
发生时来发送信号,并且在每帧运行时创建一个介于0和1之见的线性插值(interpolation)。我们可以创建一个或者多个的Animation
并附加给一个controller
当构建widget树时,你会把Anamation指定给你个widget的动画属性,比如FadeTransitionde
的opacity,并告诉控制器开始动画
如何绘图(Canvas draw/paint)
Flutter有自己的Canvas
API,因为它基于相同的底部渲染引擎Skia,因此,对于Android开发人员来说,在Flutter中绘制到画布是一项熟悉的任务,Flutter有两个类可以帮助我们绘制画布,CustomPaint和CustomPainer,它们实现您的算法以绘制到画布
例子:在线签名
import
'package:flutter/material.dart';
///在线签名
画笔void
main()=>runApp(MaterialApp(home:
DemoApp()));
class DemoApp extends
StatelessWidget{
Widget build(BuildContext
buildContext)=>Scaffold(body:Signature());
}
class Signature extends StatefulWidget{
SignatureState
createState()=>SignatureState();
}
class SignatureState extends State{
List _points = [];
@override Widget
build(BuildContext context) {
// TODO: implement build
return GestureDetector(
onPanUpdate: (DragUpdateDetails
details){
setState(() {
RenderBox referenceBox =
context.findRenderObject();
Offset localPosition =
referenceBox.globalToLocal(details.globalPosition);
_points =
List.from(_points)..add(localPosition);
});
},
onPanEnd:(DragEndDetails
details)=>_points.add(null)
,
child:
CustomPaint(painter:
SignaturePainter(_points),size:Size.infinite),
);
}
}
class SignaturePainter
extends CustomPainter{
SignaturePainter(this.points);
final List
points;
void paint(Canvas canvas,Size
size){
var paint =
Paint()
..color = Colors.black ..strokeCap =
StrokeCap.round ..strokeWidth=5.0;
for(int i=0
;i<points.length-1;i++){
if(points[i]!=null && points[i+1]!=null)
canvas.drawLine(points[i],points[i+1],
paint);
}
}
bool shouldRepaint(SignaturePainter
other)=>other.points !=points;
}
绘制圆形和方形
在Flutter 中,你可以使用CustomPaint 和CustomPainter
类去绘制到画布
使用customPaint Widget 在绘制阶段绘制,它实现了抽象类
customPainter,并将其传递给customPaint 的painter属性。customPaint
子类必须实现paint和shouldRepaint方法。
import
'package:flutter/material.dart';
///绘制圆形和方形void
main() =>runApp(MyApp());
class MyApp extends
StatelessWidget{
@override Widget build(BuildContext context)
{
// TODO: implement build
return new MaterialApp(
title: 'Flutter bottomNavigationBar',
theme: new
ThemeData.fallback(),
home: _MyCanvas(),
);
}
}
//Flutterclass MyCanvasPainter
extends CustomPainter{
@override void paint(Canvas canvas,
Size size) {
Paint paint = Paint();
paint.color = Colors.amber;
canvas.drawCircle(Offset(100.0,
200.0), 40.0, paint);
Paint paintRect = Paint();
paintRect.color = Colors.cyan;
Rect rect =
Rect.fromPoints(Offset(150.0,
300.0), Offset(300.0,
150.0));
canvas.drawRect(rect, paintRect);
}
@override bool shouldRepaint(MyCanvasPainter
oldDelegate) {
return false;
}
@override bool
shouldRebuildSemantics(MyCanvasPainter oldDelegate) {
return false;
}
}
class _MyCanvas extends
StatelessWidget{
@override Widget build(BuildContext context)
{
// TODO: implement build
return Scaffold(
body: CustomPaint(
painter: MyCanvasPainter(),
),
);
}
}
如何构建自定义widgets
在Flutter
中,推荐组合多个小的Widgets 来构建一个自定义的Widget(而不是扩展它)。
举个例子,如果你要构建一个customButton,并在构建器中传入它的label?那就组合Raiseon 和
label,而不是扩展Raiseon 。
例子:
class CustomButton extends
StatelessWidget{
final String label;
CustomButton(this.label);
@override Widget build(BuildContext context)
{
// TODO: implement build
return new Raiseon(onPressed: (){},child:
new Text(label));
}
// 调用使用自定义组件
@override Widget build(BuildContext context)
{
// TODO: implement build
return new
CustomButton('hell0');
}
}
如何设置Widget的透明度?
在Flutter中 如果要改变透明度,我们可以给widget包裹一个
Opacity widget 来做到这一点
如:
Opacity(
opacity :0.5,
child
:Text ('透明度50%')
)
布局与列表
(1)LinearLayout 在Flutter中等价于什么
在Android 中,使用LinearLayout
来使你的控件呈水平或垂直排列。在Flutter中,你可以使用Row或Colomn
widget来实现相同的结果
例子:
class MyApp
extends StatelessWidget{
@overrideWidget build(BuildContext context)
{
// TODO: implement build
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Row one'),
Text('Row Two'),
Text('Row Three'),
Text('Row Four'),
],
);
}
}
例子:
class MyColumn extends
StatelessWidget{
@overrideWidget build(BuildContext context)
{
// TODO: implement build
return Column(
mainAxisAlignment:MainAxisAlignment.center,
children: [
Text('Column one'),
Text('Column Two'),
Text('Column Three'),
Text('Column Four'),
],
);
}
}
(2)RelativeLayout在Flutter中等价于什么
RelativeLayout
用于使Widget相当于对于彼此位置排列。在Flutter中,可以通过使用Column、Row、和 Stack 的组合来实现
RelativieLayout的效果
(3)如何使用Widget在定义布局属性
在Flutter中,布局主要由专门设计用于提供布局的小部件定义,并结合控件widget及其样式属性。
(4)如何分层布局
Flutter使用Stack widge控制子widget在一层
,子widgets可以完全或部分覆盖基础widgets。
Stack
控件将其子项相对于其框的边缘定位。如果你想重叠多个子窗口小部件,这个类很有用
例子:
import
'package:flutter/material.dart';
//stack widget
类似Android中的framelayout
分层布局void
main()=>runApp( new MyApp());
class MyApp extends
StatelessWidget{
@override Widget build(BuildContext context)
{
// TODO: implement build
return new MaterialApp(
home: new MyStack(),
);
}
}
class MyStack extends
StatelessWidget{
var textStyle =
TextStyle(fontSize: 32,color:
Colors.cyan,fontWeight:
FontWeight.bold);
@override Widget build(BuildContext context)
{
// TODO: implement build
return new Scaffold(
appBar: AppBar(
title: Text(
'stack widget',
style: textStyle,
),
),
body:Stack(
children: [
Container(
width: 100.0,
height: 100.0,
color: Colors.amber,
) ,
Container(
width: 80.0,
height: 80.0,
color: Colors.pink,
),
Container(
width: 50.0,
height: 50.0,
color: Colors.cyan,
)
],
),
);
}
}
(5)如何设置布局样式
Flutter
有自己的布局系统,padding、center、column、row
等都是widget,另外组件也是通常接受于布局样式的构造参数:比如 Text widget 可以使用textStyle
属性,如果要在多个位置上使用相同的文本样式,你可以创建一个textstyle 类 并将其应用于各个text widget
(6)scrollview在Flutter中等价于什么
Flutter中用Listview替代
(7)谁是Flutter的列表组件
可以用listview来实现
例子:
import
'package:flutter/material.dart';
//listview
滚动条目void
main()=>runApp(new MyApp());
class MyApp extends
StatelessWidget{
@override Widget build(BuildContext context)
{
// TODO: implement build
return new MaterialApp(
title: 'Sample List',
theme: ThemeData(
primarySwatch: Colors.cyan ),
home: SampleAppPage(),
);
}
}
class SampleAppPage extends
StatefulWidget{
SampleAppPage({Key key}):super(key:key);
@override State createState() {
// TODO: implement createStatex
return MyListApp();
}
}
class MyListApp extends State{
@override Widget build(BuildContext context)
{
return Scaffold(
appBar: AppBar(
title: Text('Sample listview'),
//这里显示titlebar要显示的 ),
body: ListView(children:_getListData()),
);
}
}
_getListData(){
List widgets = [];
for(int i=0;i<
>100;i++){
widgets.add(Padding(padding:
EdgeInsets.all(10.0),child:
Text('Row $i')));
}
return widgets;
}
(8)如何动态更新Listview
在Flutter中,如果想通过setState()方法更新widget列表,你会很快发现你的数据展示并没有什么变化,这是因为当setState()被调用的时候,Flutter渲染引擎回去检查widget树来查看是否什么地方改变了,当它得到你的listview时,它会使用一个==判断
,并且发现两个listview是相同的。没有什么东西是变了的。因此更新不是必须的。
一个更新Listview的简单办法是,在setState()中创建一个List,并把旧的list的数据拷贝给新的list
,虽然这样很简单,但是数据集很大时候,并不推荐这样做
高效的且有效的做法是:使用Listview.Builder
来构建列表。这个方法在你想要的构建动态列表,或是列表拥有大量数据时候非常好用
创建一个Listview.Builder 要接收2个参数 :列表的初始长度 和 ItemBuilder
方法
例子:
import
'package:flutter/material.dart';
//listview 动态更新数据
采用Listview.Buildervoid main()=>runApp(new
SampleApp());
class SampleApp extends
StatelessWidget{
@override Widget build(BuildContext context)
{
// TODO: implement build
return MaterialApp(
title: 'sample app',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SampleAppPage(),
);
}
}
class SampleAppPage extends
StatefulWidget{
SampleAppPage({Key key}):super(key : key);
@override State createState() {
return _SampleAppPageState();
}
}
class _SampleAppPageState extends
State{
List widgets = [];
@override void initState() {
super.initState();
for(int i=0;i<
>100;i++){
widgets.add(getRow(i));
}
}
@override Widget build(BuildContext context)
{
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('AppListview state'),
),
body:ListView.builder(
itemCount: widgets.length,
itemBuilder: (BuildContext context,int position){
return getRow(position);
}),
);
}
Widget getRow(int i){
return GestureDetector(
child: Padding(
padding:
EdgeInsets.all(10.0),
child: Text('Row $i')
),
onTap: (){
setState((){
widgets.add(getRow(widgets.length+1));
print('row $i');
});
},
);
}
}
状态管理
(1)什么是statelessWidget
Flutter 中的statelessWidget
是一个不需要改变状态的widget-它没有要管理的内部状态
当您描述的界面部分不依赖于对象本身中的配置信息以及widget的buildContext时,无状态的widget
非常有用。
aboutDialog,
CircleAvator 和 Text 都是 stateLessWidget
无状态的widget的build方法通常只会在以下三种情况下调用:
1
将widget插入树种时
2
当widget的父级更改其配置时
3
当它依赖的inheritedWidget发生变化时候
(2)什么是statefullWidget
statefullWidget是可变状态的widget。使用setstate方法管理statefullWidget的状态的改变,用setState告诉Flutter框架,某个状态发生了变化,Flutter会重新运行build方法
以便应用程序可以应用最新状态
状态是在构建widget时可以同步读取的信息可能会在widget的声明周期中发生比阿奴哈。确保在状态改变时通知状态变化是widget实现者的责任。当widget可以动态更改时,需要使用statefullwidget。例如通过键入表单或移动滑块来更改widget的状态,或者,它可以随时间变化
或者 数据推送更新UI
checkbox , Radio ,
Slider , InkWell , Form 和 TextField 都是有状态的widget,
都是statefullwidget的子类
(3)什么是statefullWidget和statelessWidget的最佳实践
路由与导航
(1)Flutter中intent等价于什么?
在Android中,intent
主要由2中使用场景:在Acitivty之间切换,已经调用外部组件。Flutter不具Intents概念。如果要使用的话,Flutter可以通过Native整合来触发Intents
Intent 调用外部组件如:相机,文件选择器等,在flutter中实现类似的功能可以借助第三方插件
官网地址:https://pub.dev/packages
(2)Flutter中如何实现不同页面中的跳转?
(3)Flutter中路由跳转返回的结果?
(4)如果在Flutter中处理来自外部应用程序传入的intents?
然后 在mainactvity
中处理intnet,一旦从intent中获取到共享数据,我们就会持有它,直到Flutter在完成准备就绪时候请求它
最后,在Flutter中 ,可以渲染Flutter视图时请求数据
(5)怎么跳转到其他App?
在Flutter中实现这个功能,你可以创建一个原声平台的整合层,或者使用现有的plugin,例如url_launcher
线程和异步UI
(1)怎么编写异步代码
Dart有一个单线程执行模式,支持Isolate(一种在另一个线程上运行的Dart代码的方法),一个事件循环和异步编程。除非你自己创建一个Isolate,否则你的Dart代码永远运行在主UI线程,并由event
loop驱动,Flutter的 evnet loop 和ios的main
loop相似:looper是附加在主线程上的。
Dart的单线程模型,并不意味着你写的代码一定要作为阻塞操作的方式运行,从而卡住UI。相反,可以使用Dart语言提供的异步工具,例如async/await,
来实现异步操作。
举个例子:使用async/await
来让Dart帮你做一些繁重的工作,编写网络请求代码而不会挂起UI:
loadData() async
{
String dataUrl
='https://jsonplaceholder.typicode.com/posts';
http.Response response =
await http.get(dataUrl);
setState((){ //setState更新ui
这里做法类似 Android中的runOnuithread
widgets =
json.decode(response.body);
})
}
loadData()
async {
String dataUrl =
'https://jsonplaceholder.typicode.com/posts';
http.Response response = await
http.get(dataUrl);
print('test'+response.body);
setState(() {
widgets =
json.decode(response.body);
});
}
以上就是对网络操作,数据库访问,I/O操作的典型做法
Isolate是分离的运行线程,并且不和主线程的内存堆共享内存,这意味着你不能访问主线程中
的变量,或者使用setState()来更新UI,即Isolate不能共享内存。
发送网络请求,在http.get()
这个async方法中使用 await:
import
'package:flutter/material.dart';
import
'dart:convert';
import
'package:http/http.dart' as http;
loadData() async {
String dataUrl =
'https://jsonplaceholder.typicode.com/posts';
http.Response response = await
http.get(dataUrl);
print('test'+response.body);
setState(() {
widgets =
json.decode(response.body);
});
}
获取结果 用setState()更新Flutter的UI;
(4) 如何为长时间运行的任务添加一个进度条
在Flutter中对应的widget叫progressIndicator。
通过布尔值来控制是否显示进度。在任务开始时,告诉Flutter更新状态,任务结束后隐藏
(3) 如何进行网络请求
要是用http包,在pubspec.yaml
中添加依赖
dependencies:
...
http:^0.12.0+1
(2)怎么把工作放到后台线程执行
由于Flutter
是单线程并且跑着一个event
loop(就像Node.js),因此你不必担心线程管理或生成后台线程。如果让你做I/O操作,如访问磁盘或者网络请求,可以安全的使用async/await来完成
。如果你需要让cpu执行繁忙的计算密集型任务,你需要使用Isolate来避免evenet
loop.
对于I/O操作,通过关键字async把方法声明为异步方法,然后通过await关键字等待该异步方法执行完成
手势监测及触摸事件处理
(1)
如何给Flutter的widget添加点击事件的监听
Flutter中有2种方式来添加点击监听者:
1
如果widget本身支持事件监测,直接传递给他一个函数,饼子啊函数里实现相应方法。例如,raiseon widget
拥有onpRessed 参数
class
SampleApp extends
StatelessWidget{
@override Widget build(BuildContext context)
{
// TODO: implement build
return Raiseon(
onPressed: (){
print('click');
},
child: Text('Button'),
);
}
}
2
如果widget本身不支持事件监听,则在外面包裹一个GestureDetector,并给它onTap属性传递一个函数:
例子 :
class GestrueApp extends
StatelessWidget{
@overrideWidget build(BuildContext context)
{
// TODO: implement build
return Scaffold(
body: Center(
child: GestureDetector(
child: FlutterLogo(
size: 200.0,
),
onTap: (){
print('tap');
},
),
),
);
}
}
3如何处理widget上的其他手势
使用
GestureDetector,可以监听多种手势
1点击
# onTapDown
在特定位置上轻触手势接触了屏幕
#onTapUp
在特定位置产生了轻触手势,并停止接触屏幕
#onTap
产生了一个轻触手势
# onTapCancel
出发了onTapDown 但是没触发tap
2 双击
#onDoubleTap
用户在同一个位置长时间接触屏幕
3 垂直拖动
#onVerticalDragStart
接触了屏幕,并且可能会垂直移动
#onVerticalDragUpdate
接触了屏幕,并继续在垂直方向移动
#onVerticalDragEnd
之前接触了屏幕并垂直移动,并在停止接触屏幕前以某个垂直的速度移动
3 水平拖动
#onHorizontalDragStart 接触了屏幕
,并且可能会水平移动
#onHorizontalDragUpdate
接触了屏幕 ,并继续水平移动
#onHorizontalDragEnd
之前接触了屏幕 ,并水平移动的触摸点与屏幕分离
主题和文字处理
在Flutter中,只需要在文件夹中放置字体文件,并在pubspec.yaml
中引用它,就像添加图片那样
fonts:
-
family: Schyler fonts: - asset:
fonts/Schyler-Regular.ttf style: italic
然后通过如下方式使用字体:
class
MyFont extends
StatelessWidget{
@override Widget build(BuildContext context)
{
return Scaffold(
appBar: AppBar(
title: Text('Sample'),
),
body: Center(
child: Text('this is a custom font
text',
style: TextStyle(fontFamily:
'Schyler'),
),
),
);
}
}
(2) 如何在Text上定义样式
除了字体意外,你也可以给Text widget 的样式元素设置自定义值。Text
widget
接收一个TextStyle对象,你可以指定许多参数,如下:
color
decoration
decorationColor
decorationStyle
fontFamily
fontSIze
fontStyle
fontWeight
hashCode
height
inherit
letterSpacing
textBaseline
wordSpacing
(3) 如何给App设置主题
(1) 如何设置字体样式
>表单输入与富文本
(1) 如何获取用户的输入
在Flutter
中我们使用TextField活TextFormField ,然后通过
TextEditingController来获取用户输入。
(2) 如何设置输入框的提示文字
在Flutter中,你可以通过向Text
Widget的装饰构造器参数设置一个inputDecoration来展示’小提示‘,伙食占位符文字
body :Center(
child
:TextField(
decoration:inputDecoration(hintText:'this is a
hint'),
),
)
(3)如何显示验证错误信息
TextField的decoration参数为他设置一个InputDecoration,我们借助inputDecoration
除了可以添加提示信息外,还可以添加错误信息 :
decoration:inputDecoration(hintText:'This is a
hint',erroText:
'错误提示')
调用硬件、第三方服务以及平台交互、通知
(1)
如何调用硬件与第三方服务
在Flutter中调用硬件与第三方服务都是可以通过集成对应的插件来完成:
1
用于访问位置信息GPS的插件:geolocator;
2
用于访问相册与相机的插件:image_picker;
3 本地存储
:用于ios的userDefaults与Android的sharedPreference插件:Shared
Preferences
plugin
4 用于访问数据的插件:SQFlite
5
用于呼唤起第三方登录FaceBook的插件:flutter_facebook_login;
6 用于推送通知的插件 :firebase_messaging
7 用于使用Firebase的插件
:firebase
plugin
关于Flutter的更多的插件,可以在(2)
如何构建与集成Native Sdk /模块