先说用到的3个文件
- pubspec.yaml 安装必要包
- AndroidManifest.xml 添加权限(android/src/main)
- api.dart 封装一些系统的方法 (lib/utils)
- main.dart 初始化时,获取可用照相机,省去拍照页面的等待黑屏时间
- camera 拍照demo
pubspec.yaml
camera: ^0.5.6+3
path_provider: ^1.4.4
AndroidManifest.xml
<!-- 获取相机权限 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 储存权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
api.dart
import 'package:camera/camera.dart';
List<CameraDescription> cameras;
CameraController controller;
// 获取照相机
Future<void> getCamera() async {
cameras = await availableCameras();
}
mian.dart
import './utils/api.dart';
import './mainPage.dart';
Future<void> main() async {
getCamera();
runApp(MyApp());
}
// 省略 .....
camera.dart 重点来了
- imagePath 用来保存拍照的地址
- initState时获取后摄像头,如果用前摄像头(cameras[1])
class CameraPageState extends State<Camera> {
String imagePath ;
@override
void initState(){
super.initState();
// 调用相机
controller = CameraController(cameras[0], ResolutionPreset.medium);
controller.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
页面布局,上方显示 拍照预览,下方为按钮
Widget build(BuildContext context) {
return Scaffold(
body:new Container(
child:Stack(children: <Widget>[
new Column(
children: <Widget>[
Expanded(
flex: 3,
child: _cameraPreviewWidget(),
),
Expanded(
flex: 1,
child: _takePictureLayout()
)
],
),
getPhotoPreview()
],)
)
);
}
相机预览显示
Widget _cameraPreviewWidget() {
print(controller);
if (controller == null || !controller.value.isInitialized) {
return new Scaffold(
appBar: AppBar(
title: const Text('camera'),
),
body: GestureDetector(
onTap:(){
print('已被点击');
onTakePictureButtonPressed();
},
child: Text('点我拍照')
)
);
}
return new Container(
child:AspectRatio(
aspectRatio:controller.value.aspectRatio,
child: CameraPreview(controller),
)
);
}
拍照按钮布局
Widget _takePictureLayout() {
return new Align(
alignment: Alignment.bottomCenter,
child: new Container(
color: Colors.black,
alignment: Alignment.center,
child: new IconButton(
iconSize: 50.0,
onPressed: controller != null &&
controller.value.isInitialized &&
!controller.value.isRecordingVideo
? onTakePictureButtonPressed
: null,
icon: Icon(
Icons.photo_camera,
color: Colors.white,
),
),
));
}
拍完预览
Widget getPhotoPreview() {
if( null != imagePath){
return new Container(
width:double.infinity,
height: double.infinity,
color: Colors.black,
alignment: Alignment.center,
child: Image.file(File(imagePath)),
);
}else{
return new Container(
height: 1.0,
width: 1.0,
color: Colors.black,
alignment: Alignment.bottomLeft,
);
}
}
保存图片操作
String timestamp() => DateTime.now().millisecondsSinceEpoch.toString();
Future<String> takePicture() async {
if (!controller.value.isInitialized) {
// showInSnackBar('Error: select a camera first.');
return null;
}
// getApplicationDocumentsDirectory 文档目录
final Directory extDir = await getExternalStorageDirectory();
final String dirPath = '${extDir.path}/Pictures/flutter_test';
print(dirPath);
await Directory(dirPath).create(recursive: true);
final String filePath = '$dirPath/${timestamp()}.jpg';
print(filePath);
if (controller.value.isTakingPicture) {
// A capture is already pending, do nothing.
return null;
}
try {
await controller.takePicture(filePath);
print('保存成功');
} on CameraException catch (e) {
print('保存失败');
print(e);
return null;
}
return filePath;
}
网友评论