Flutter
Flutter 由 Flutter Engine 和 Dart 实现,Flutter Engine 负责线程管理,Dart VM 状态管理和 Dart 代码加载等工作。而 Dart 代码所实现的 Framework 则是业务接触到的主要 API,诸如 Widget 等概念就是在 Dart 层面 Framework的内容。
下图flutter的框架结构诠释了渲染以及实现的方式
Flutter 从一开始就是为纯 Flutter 应用设计的,纯 Flutter 应用整个运行生命周期都只有一个 FlutterView 和 Root Isolate,依靠 Flutter Framework 自身 Route 支持在 FlutterView 内部完成界面跳转
-
一个 FlutterView 对应一个 FlutterEngine 实例;
-
一个 FlutterEngine 实例对应一个 Dart Isolate 实例;
-
同一个进程只有且仅有一个 Dart VM 虚拟机;
-
一个 Dart VM 上会存在多个 Dart Isolate 实例,Isolate 是 dart 代码的执行环境;
Flutter 和其他跨平台方案的本质区别:
- React Native 之类的框架,只是通过 JavaScript 虚拟机扩展调用系统组件,由 Android 和 iOS 系统进行组件的渲染;
- 上层是js语言,通过中间层 bridge,再由Android 和 iOS 系统进行组件的渲染
- 对接不同平台会有些差异,无法统一
- Flutter 则是自己完成了组件渲染的闭环
- 不同平台不需要写iOS 或者 Android 不同的组件渲染接口
- 少了中间层bridge的开销,性能会更快
初始化-配置
ios 开发模式为例
-
Visual Studio Code
-
macOs 10.13 以上
-
Xcdoe
- 配置完成后,输入命令 open -a Simulator 打开 iOS 模拟器
-
flutter sdk 安装包
- 编辑 ~/.bash_profile 文件,
export PATH="$PATH:pwd/flutter/bin"将 flutter 命令的执行路径追加到环境变量 PATH 中
- 编辑 ~/.bash_profile 文件,
-
create the app
cd flutter_app
export PATH="$PATH:`pwd`/flutter/bin"
echo $PATH
which flutter
open -a Simulator
flutter create my_app
cd my_app
flutter run
小试牛刀 hello word
widget
Flutter 中都是 Widget,包括应用、视图、视图控制器、布局等在内的概念,都建立在 Widget 之上, build 方法中,我们通常通过对基础 Widget 进行相应的 UI 配置,或是组合各类基础 Widget 的方式进行 UI 的定制化。比如在 MyApp 中,我通过 MaterialApp 这个 Flutter App 框架设置了应用首页,即 MyHomePage。当然,[MaterialApp] (api.flutter.dev/flutter/mat…)也是一个 Widget,可以参考API设计不同的风格.
StatefulWidget有状态组件 这类Widget(比如 Image、Checkbox)的展示,除了父 Widget 初始化时传入的静态配置之外,还需要处理用户的交互(比如,用户点击按钮)或其内部数据的变化(比如,网络数据回包),并体现在 UI 上。
StatelessWidget无状态组件比如 Text、Container、Row、Column 等)在创建时,通过父widget的初始化获得配置参数之外不依赖于任何其他信息)
hello word
MyApp 为 Flutter 应用的运行实例,通过在 main 函数中调用 runApp 函数实现程序的入口。而应用的首页则为 MyHomePage,一个拥有 _MyHomePageState 状态的 StatefulWidget。_MyHomePageState 通过调用 build 方法,以相应的数据配置完成了包括导航栏、文本及按钮的页面视图的创建。
官网demo解读如下:
手势 - 手势密码
- 指针事件
- 手势识别
手指接触屏幕 PointerDownEvent、手指在屏幕上移动 PointerMoveEvent、手指抬起 PointerUpEvent,以及触摸取消 PointerCancelEvent
手势语义操作的 Gesture,如点击 onTap、双击 onDoubleTap、长按 onLongPress、拖拽 onPanUpdate、缩放 onScaleUpdate 等
Flutter 提供了 Listener Widget,可以监听其子 Widget 的原始指针事件, 以及 Arena 用来识别究竟哪个手势可以响应用户事件。
main.dart 文件如下
import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: Scaffold(
body: TabBarView(
physics: NeverScrollableScrollPhysics(),
children: [
ListenerWidget(), // Flutter 提供了 Listener Widget,可以监听其子 Widget 的原始指针事件
DragWidget(), // 拖拽
DoubleGestureWidget(), // 双击手势
],
),
bottomNavigationBar: TabBar(
tabs: [
Tab(icon: Icon(Icons.home),text: "指针事件",),
Tab(icon: Icon(Icons.rss_feed),text: "手势",),
Tab(icon: Icon(Icons.perm_identity),text: "手势冲突",)
],
unselectedLabelColor: Colors.blueGrey,
labelColor: Colors.blue,
indicatorSize: TabBarIndicatorSize.label,
indicatorColor: Colors.red,
),
),
);
}
}
class ListenerWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Listener(
child: Container(
color: Colors.red,
width: 300,
height: 300,
),
onPointerDown: (event) => print("down $event"),
onPointerMove: (event) => print("move $event"),
onPointerUp: (event) => print("up $event"),
)
);
}
}
class DragWidget extends StatefulWidget {
@override
_DragState createState() => new _DragState();
}
class _DragState extends State<DragWidget> {
double _top = 0.0; //距顶部的偏移
double _left = 0.0;//距左边的偏移
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("demo"),),
body: Stack(
children: <Widget>[
Positioned(
top: _top,
left: _left,
child: GestureDetector( // 手势识别
child: Container(color: Colors.red,width: 50,height: 50),
onTap: ()=>print("Tap"),
onDoubleTap: ()=>print("Double Tap"),
onLongPress: ()=>print("Long Press"),
onPanUpdate: (e) {
setState(() { // 触发状态更新
_left += e.delta.dx;
_top += e.delta.dy;
});
},
),
)
],
)
);
}
}
class DoubleGestureWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: RawGestureDetector(
gestures: {
MultipleTapGestureRecognizer: GestureRecognizerFactoryWithHandlers<
MultipleTapGestureRecognizer>(
() => MultipleTapGestureRecognizer(),
(MultipleTapGestureRecognizer instance) {
instance.onTap = () => print('parent tapped '); // 父视图的点击回调
},
)
},
child: Container(
color: Colors.pinkAccent,
child: Center(
child: GestureDetector(
onTap: () => print('Child tapped'), // 子视图的点击回调
child: Container(
color: Colors.blueAccent,
width: 200.0,
height: 200.0,
)),
),
),
)
);
}
}
class MultipleTapGestureRecognizer extends TapGestureRecognizer {
@override
void rejectGesture(int pointer) {
acceptGesture(pointer);
}
}
相关的ios 手势密码开发
-
手势密码中的圆点
-
手势绘制 View
-
展示ui
-
GesturesViewController:这个 controller 用于展示 UI,你可以替换成自己 controller,
-
GesturesView:用于圆点按钮的初始化和布局,
-
PointView:圆点手势按钮。
plugin 调用native的功能- camera
- pubspec.yaml添加所需的依赖项。
- flutter
- sdk: flutter
- camera:">=0.5.7"
- path_provider:^0.5.0
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
camera: "0.5.7"
# path_provider: "/Users/Documents/ppt/pic/"
# path: "/Users/Documents/ppt/pic/"
# path: "../"
path_provider: ^0.5.0
//
flutter pub get
ios 配置 info.plist
<key>NSCameraUsageDescription</key>
<string>Can I use the camera please?</string>
<key>NSMicrophoneUsageDescription</key>
<string>Can I use the mic please?</string>
- 获取可用摄像机的列表。
- 创建并初始化CameraController。
- CameraPreview 显示摄像机的源。
- CameraController相机控制器拍照。
- 使用Image widget显示图片。
社区问题
- 新项目可以直接尝试
- 旧项目flutter如何于native共存,数据状态的管理(阿里,字节调动)
- 性能
- 虽然 Flutter 内部通过 Element 层可以最大程度地降低对真实渲染视图的修改,提高渲染效率,而不是销毁整个 RenderObject 树重建。但,大量 Widget 对象的销毁重建是无法避免的。如果某个子 Widget 的重建涉及到一些耗时操作,那页面的渲染性能将会急剧下降。
- 合理使用StatefulWidget有状态组件 StatelessWidget无状态组件