Flutter 使用 camera 拍摄照片及预览
一、camera 插件
camera
是 Flutter 提供的相机相关的插件,内部封装了相机相关的 Native API,通过 camera
插件能够获取当前设备相机列表,并且选择一个可用相机展示相机预览、拍照和录制视频等
要使用 camera 插件,添加依赖,一般我们还需要 path_provider 和 path 两个包,用于存储和获取照片
dependencies:
flutter:
sdk: flutter
camera:
path_provider:
path:
二、availableCameras 获取设备可用的相机列表
availableCameras
是 camera.dart
提供的用于获取设备上相机列表的方法
Native 会将设备相机列表通过通信传递给 Flutter,然后再返回一个 List
return cameras.map((Map<dynamic, dynamic> camera) {
return CameraDescription(
name: camera['name'],
lensDirection: _parseCameraLensDirection(camera['lensFacing']),
sensorOrientation: camera['sensorOrientation'],
);
}).toList();
方法都是异步的,因此获取设备的一个主摄像头(一般是后置)可以通过如下方式:
// Obtain a list of the available cameras on the device.
final cameras = await availableCameras();
// Get a specific camera from the list of available cameras.
final firstCamera = cameras.first;
当然,你可以通过判断相机列表来判断是否有可用相机,然后做一个提示
final cameras = await availableCameras();
Widget _body;
if (cameras.length > 0) {
_body = HomeContent(camera: cameras[0]);
} else {
_body = Center(child: Text('No Cameras'));
}
三、创建 CameraController 及初始化
拿到设备相机之后,就可以创建 CameraController
:
_cameraController = CameraController(widget.camera, ResolutionPreset.medium);
CameraController
需要传入两个顺序参数,分别是描述和预设分辨率
CameraController(
this.description,
this.resolutionPreset, {
this.enableAudio = true,
})
description 需要是 CameraDescription
类型
ResolutionPreset 有三个预设值分别是 low
/medium
/high
拿到 Controller 之后,就可以初始化设备上的相机,提供了 initialize()
方法
_initializeControllerFuture = _cameraController.initialize();
当然在 Widget 销毁的时候,需要将 CameraController 移除:
@override
void dispose() {
_cameraController.dispose();
super.dispose();
}
四、使用 CameraPreview 预览相机
拍照一般我们都会有一个预览窗口,预览窗口能够实时看到相机看到的内容
CameraPreview
使用很简单,只需要将 CameraController 的实例作为参数区实例化出 CameraPreview 即可。
CameraPreview 的宽度高度则是依赖父容器,一般用一个 Container:
return Container(
child: CameraPreview(_cameraController),
width: 400,
height: 300,
);
当然,我们可以发现,CameraContoller.initialize()
方法也是异步的,如果需要等待异步完成在渲染页面,就需要使用 FutureBuilder
去渲染 Widget。
下面代码中,当 _initializeControllerFuture
完成的时候,才将 CameraPreview 渲染:
FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the Future is complete, display the preview.
return Container(
child: CameraPreview(_cameraController),
width: 400,
height: 300,
);
} else {
// Otherwise, display a loading indicator.
return Center(child: CircularProgressIndicator());
}
},
五、使用 takePicture 拍照
CameraController 提供了 takePicture
进行拍照, Future<void> takePicture(String path) async {}
拍照的时候需要将 path
也就是保存的路径传入
生成路径一般我们需要选择一个存储的文件夹,通过 path_provider
提供,通过 path
将路径组装起来
下面代码中,通过时间戳生成一个 path,然后再拼接整个路径:
try {
await _initializeControllerFuture;
final dateTime = DateTime.now();
final path = join((await getTemporaryDirectory()).path,
'${dateTime.millisecondsSinceEpoch}.png');
await _cameraController.takePicture(path);
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => DisplayPictureScreen(imagePath: path),
));
Scaffold.of(context).showSnackBar(SnackBar(content: Text(path)));
} catch (err, stack) {
print(err);
}
注意:上面代码中,await _initializeControllerFuture;
确保已经初始化过了 CameraController
通过 SnackBar 显示路径:
六、效果
七、完整代码
https://github.com/postbird/FlutterHelloWorldDemo/blob/dev1/demo1/lib/bak/main.56-Camera.dart
文章版权:Postbird-There I am , in the world more exciting!
本文链接:http://www.ptbird.cn/flutter-camera.html
转载请注明文章原始出处 !
请问拍下来的照片如何旋转并重新保存
请问照片保存到哪儿了,手机里为啥找不到呢
请问待机久了预览不显示了 怎么解决