android - 如何从相机捕获图像,包括覆盖小部件?
问题描述
我已经使用camera
包创建了一个相机处理程序。结果如下所示:
我希望在捕获的图像中包含除捕获和返回按钮之外的时钟和用户配置文件等叠加层,是否可以这样做?
或者也许我应该使用有条件的屏幕截图而不是使用捕获功能?
提前致谢!
编辑
这是我的camera.dart
样子:
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart';
import 'package:path_provider/path_provider.dart';
List<CameraDescription> cameras;
class CameraPage extends StatefulWidget {
final int cameraIdx;
CameraPage({
Key key,
@required this.cameraIdx,
}) : super(key: key);
@override
_CameraPageState createState() => _CameraPageState();
}
class _CameraPageState extends State<CameraPage> {
CameraController controller;
List cameras;
int selectedCameraIdx;
String imagePath;
String _timeString;
Timer _timer;
void _getTime() {
final DateTime now = DateTime.now();
final String formattedDateTime = _formatDateTime(now);
setState(() {
_timeString = formattedDateTime;
});
}
String _formatDateTime(DateTime dateTime) =>
DateFormat('HH:mm:ss').format(dateTime);
String timestamp() => DateTime.now().millisecondsSinceEpoch.toString();
// Initialize camera controller
Future _initCameraController(CameraDescription cameraDescription) async {
if (controller != null) {
await controller.dispose();
}
// set controller by the camera description with high resolution preset
controller = CameraController(cameraDescription, ResolutionPreset.high);
// If the controller is updated then update the UI.
controller.addListener(() {
// when this widget is mounted clear the state
if (this.mounted) {
setState(() {});
}
if (controller.value.hasError) {
print('Camera error ${controller.value.errorDescription}');
}
});
// 6
try {
await controller.initialize();
} on CameraException catch (e) {
print(e);
}
if (this.mounted) {
setState(() {});
}
}
Future<String> takePicture() async {
if (!controller.value.isInitialized) {
return null;
}
final Directory extDir = await getExternalStorageDirectory();
final String dirPath = '${extDir.path}/Pictures/flutter_test';
await Directory(dirPath).create(recursive: true);
final String filePath = '$dirPath/${timestamp()}.jpg';
if (controller.value.isTakingPicture) {
// A capture is already pending, do nothing.
return null;
}
try {
await controller.takePicture(filePath);
} on CameraException catch (e) {
_showCameraException(e);
return null;
}
return filePath;
}
void logError(String code, String message) =>
print('Error: $code\nError Message: $message');
void _showCameraException(CameraException e) {
logError(e.code, e.description);
}
void onCaptureButtonPressed() {
takePicture().then((String filePath) {
print(filePath);
if (mounted) {
setState(() {
imagePath = filePath;
});
}
});
}
@override
void initState() {
super.initState();
// Check if camera available
availableCameras().then((availableCameras) {
cameras = availableCameras;
if (cameras.length > 0) {
setState(() {
// Select front camera as default
if (widget.cameraIdx != null) {
selectedCameraIdx = widget.cameraIdx;
} else {
selectedCameraIdx = 1;
}
});
_initCameraController(cameras[selectedCameraIdx]).then((void v) {});
} else {
print("No camera available");
}
}).catchError((err) {
// Print error if any
print('Error: $err.code\nError Message: $err.message');
});
_timeString = _formatDateTime(DateTime.now());
_timer = Timer.periodic(Duration(seconds: 1), (Timer t) => _getTime());
}
@override
void dispose() {
controller?.dispose();
_timer.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
final deviceRatio = size.width / size.height;
if (!controller.value.isInitialized) {
return Container();
}
return Scaffold(
body: Stack(
children: <Widget>[
Transform.scale(
scale: controller.value.aspectRatio / deviceRatio,
child: Center(
child: AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: CameraPreview(controller),
),
),
),
Align(
alignment: Alignment.topCenter,
child: Container(
width: double.infinity,
height: 110.0,
padding: EdgeInsets.only(right: 20.0),
child: Padding(
padding: EdgeInsets.only(top: 40.0, right: 0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
GestureDetector(
child: Padding(
padding: EdgeInsets.only(left: 20.0),
child: Icon(
FontAwesomeIcons.arrowLeft,
color: Colors.white,
size: 30.0,
),
),
onTap: () {
Navigator.of(context).pop();
},
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 15.0, right: 10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Text('Donny Pratama',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 16.0)),
Text(
'Front End Developer',
style: TextStyle(color: Colors.white),
)
],
),
),
CircleAvatar(
radius: 30.0,
backgroundImage:
NetworkImage('https://via.placeholder.com/150'),
backgroundColor: Colors.transparent,
)
],
),
],
),
),
),
),
Align(
alignment: Alignment.bottomLeft,
child: Container(
width: double.infinity,
height: 180.0,
padding: EdgeInsets.only(left: 20.0),
child: Align(
alignment: Alignment.topLeft,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
_timeString,
style: TextStyle(
color: Colors.white,
fontSize: 50.0,
fontFamily: 'Roboto',
),
),
Row(
children: <Widget>[
Padding(
padding: EdgeInsets.only(right: 5.0),
child: Icon(
FontAwesomeIcons.mapMarkerAlt,
color: Colors.white,
size: 12.0,
),
),
Text(
'Yogyakarta, Indonesia',
style: TextStyle(color: Colors.white),
)
],
),
],
),
],
),
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
width: double.infinity,
height: 120.0,
// color: Colors.white,
padding: EdgeInsets.all(20.0),
child: Stack(
children: <Widget>[
Align(
alignment: Alignment.center,
child: SizedBox(
width: double.infinity,
height: 60.0,
child: RaisedButton(
elevation: 0.5,
color: Colors.orange,
textColor: Colors.white,
child: Icon(FontAwesomeIcons.camera),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
onPressed: onCaptureButtonPressed,
),
),
),
],
),
),
),
],
),
);
}
}
解决方案
推荐阅读
- html - 如何以达到限制后自动开始新行的方式设置文本
- python - ttk notebook 可以嵌套吗?
- android - ':app:transformDexArchiveWithExternalLibsDexMergerForDebug'.com.android.builder.dexing.DexArchiveMergerException:
- hadoop - IDEA在hadoop源码中找不到某些包
- c# - 如何在 .NET Core 中使用默认编辑器打开文本文件
- python - 在opencv中停止并重新启动rtsp流以进行对象检测
- python-3.x - 如何将熊猫列拆分为多列
- python - 检查整数时出现逻辑错误
- c - N>47 的斐波那契数生成器中断
- html - 在 Seaside 中使用图像作为可点击项创建超链接