如何解决在颤动中单击相机按钮后手电筒重新启动
我正在尝试使用颤振中的相机插件(相机:^0.8.1+3)构建一个应用程序,在此应用程序中,我试图在手电筒打开时单击图片,但问题是它可以工作在某些 Oneplus 设备中正确,但在任何其他设备中,当我尝试单击图片时,手电筒会重新启动。我使用的是 Flutter 2。
import 'dart:async';
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:Flutter/material.dart';
import 'package:video_player/video_player.dart';
class CameraExampleHome extends StatefulWidget {
@override
_CameraExampleHomeState createState() {
return _CameraExampleHomeState();
}
}
/// Returns a suitable camera icon for [direction].
IconData getCameraLensIcon(CameraLensDirection direction) {
switch (direction) {
case CameraLensDirection.back:
return Icons.camera_rear;
case CameraLensDirection.front:
return Icons.camera_front;
case CameraLensDirection.external:
return Icons.camera;
default:
throw ArgumentError('UnkNown lens direction');
}
}
void logError(String code,String? message) {
if (message != null) {
print('Error: $code\nError Message: $message');
} else {
print('Error: $code');
}
}
class _CameraExampleHomeState extends State<CameraExampleHome>
with WidgetsBindingObserver,TickerProviderStateMixin {
CameraController? controller;
XFile? imageFile;
XFile? videoFile;
VideoPlayerController? videoController;
VoidCallback? videoPlayerListener;
bool enableAudio = true;
double _minAvailableExposureOffset = 0.0;
double _maxAvailableExposureOffset = 0.0;
double _currentExposureOffset = 0.0;
late AnimationController _flashModeControlRowAnimationController;
late Animation<double> _flashModeControlRowAnimation;
late AnimationController _exposureModeControlRowAnimationController;
late Animation<double> _exposureModeControlRowAnimation;
late AnimationController _focusModeControlRowAnimationController;
late Animation<double> _focusModeControlRowAnimation;
double _minAvailableZoom = 1.0;
double _maxAvailableZoom = 1.0;
double _currentScale = 1.0;
double _baseScale = 1.0;
// Counting pointers (number of user fingers on screen)
int _pointers = 0;
@override
void initState() {
super.initState();
WidgetsBinding.instance?.addobserver(this);
_flashModeControlRowAnimationController = AnimationController(
duration: const Duration(milliseconds: 10),vsync: this,);
_flashModeControlRowAnimation = CurvedAnimation(
parent: _flashModeControlRowAnimationController,curve: Curves.easeInCubic,);
_exposureModeControlRowAnimationController = AnimationController(
duration: const Duration(milliseconds: 10),);
_exposureModeControlRowAnimation = CurvedAnimation(
parent: _exposureModeControlRowAnimationController,);
_focusModeControlRowAnimationController = AnimationController(
duration: const Duration(milliseconds: 10),);
_focusModeControlRowAnimation = CurvedAnimation(
parent: _focusModeControlRowAnimationController,);
}
@override
void dispose() {
WidgetsBinding.instance?.removeObserver(this);
_flashModeControlRowAnimationController.dispose();
_exposureModeControlRowAnimationController.dispose();
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
final CameraController? cameraController = controller;
// App state changed before we got the chance to initialize.
if (cameraController == null || !cameraController.value.isInitialized) {
return;
}
if (state == AppLifecycleState.inactive) {
cameraController.dispose();
} else if (state == AppLifecycleState.resumed) {
onNewCameraSelected(cameraController.description);
}
}
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,appBar: AppBar(
title: const Text('Camera example'),),body: Column(
children: <Widget>[
Expanded(
child: Container(
child: Padding(
padding: const EdgeInsets.all(1.0),child: Center(
child: _cameraPreviewWidget(),decoration: Boxdecoration(
color: Colors.black,border: Border.all(
color:
controller != null && controller!.value.isRecordingVideo
? Colors.redAccent
: Colors.grey,width: 3.0,_captureControlRowWidget(),_modeControlRowWidget(),Padding(
padding: const EdgeInsets.all(5.0),child: Row(
mainAxisAlignment: MainAxisAlignment.start,children: <Widget>[
_cameraTogglesRowWidget(),_thumbnailWidget(),],);
}
/// display the preview from the camera (or a message if the preview is not available).
Widget _cameraPreviewWidget() {
final CameraController? cameraController = controller;
if (cameraController == null || !cameraController.value.isInitialized) {
return const Text(
'Tap a camera',style: TextStyle(
color: Colors.white,fontSize: 24.0,fontWeight: FontWeight.w900,);
} else {
return Listener(
onPointerDown: (_) => _pointers++,onPointerUp: (_) => _pointers--,child: CameraPreview(
controller!,child: LayoutBuilder(
builder: (BuildContext context,BoxConstraints constraints) {
return GestureDetector(
behavior: HitTestBehavior.opaque,onScaleStart: _handleScaleStart,onScaleUpdate: _handleScaleUpdate,onTapDown: (details) => onViewFinderTap(details,constraints),);
}),);
}
}
void _handleScaleStart(ScaleStartDetails details) {
_baseScale = _currentScale;
}
Future<void> _handleScaleUpdate(ScaleUpdateDetails details) async {
// When there are not exactly two fingers on screen don't scale
if (controller == null || _pointers != 2) {
return;
}
_currentScale = (_baseScale * details.scale)
.clamp(_minAvailableZoom,_maxAvailableZoom);
await controller!.setZoomLevel(_currentScale);
}
/// display the thumbnail of the captured image or video.
Widget _thumbnailWidget() {
final VideoPlayerController? localVideoController = videoController;
return Expanded(
child: Align(
alignment: Alignment.centerRight,child: Row(
mainAxisSize: MainAxisSize.min,children: <Widget>[
localVideoController == null && imageFile == null
? Container()
: SizedBox(
child: (localVideoController == null)
? Container(child: Image.file(File(imageFile!.path)))
: Container(
child: Center(
child: AspectRatio(
aspectRatio:
localVideoController.value.size != null
? localVideoController
.value.aspectRatio
: 1.0,child: VideoPlayer(localVideoController)),decoration: Boxdecoration(
border: Border.all(color: Colors.pink)),width: 64.0,height: 64.0,);
}
/// display a bar with buttons to change the flash and exposure modes
Widget _modeControlRowWidget() {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,mainAxisSize: MainAxisSize.max,children: <Widget>[
IconButton(
icon: Icon(Icons.flash_on),color: Colors.blue,onpressed: controller != null ? onFlashModeButtonpressed : null,IconButton(
icon: Icon(Icons.exposure),onpressed:
controller != null ? onExposureModeButtonpressed : null,IconButton(
icon: Icon(Icons.filter_center_focus),onpressed: controller != null ? onFocusModeButtonpressed : null,IconButton(
icon: Icon(enableAudio ? Icons.volume_up : Icons.volume_mute),onpressed: controller != null ? onAudioModeButtonpressed : null,IconButton(
icon: Icon(controller?.value.isCaptureOrientationLocked ?? false
? Icons.screen_lock_rotation
: Icons.screen_rotation),onpressed: controller != null
? onCaptureOrientationLockButtonpressed
: null,_flashModeControlRowWidget(),_exposureModeControlRowWidget(),_focusModeControlRowWidget(),);
}
Widget _flashModeControlRowWidget() {
return SizeTransition(
sizefactor: _flashModeControlRowAnimation,child: ClipRect(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: [
IconButton(
icon: Icon(Icons.flash_off),color: controller?.value.flashMode == FlashMode.off
? Colors.orange
: Colors.blue,onpressed: controller != null
? () => onSetFlashModeButtonpressed(FlashMode.off)
: null,IconButton(
icon: Icon(Icons.flash_auto),color: controller?.value.flashMode == FlashMode.auto
? Colors.orange
: Colors.blue,onpressed: controller != null
? () => onSetFlashModeButtonpressed(FlashMode.auto)
: null,IconButton(
icon: Icon(Icons.flash_on),color: controller?.value.flashMode == FlashMode.always
? Colors.orange
: Colors.blue,onpressed: controller != null
? () => onSetFlashModeButtonpressed(FlashMode.always)
: null,IconButton(
icon: Icon(Icons.highlight),color: controller?.value.flashMode == FlashMode.torch
? Colors.orange
: Colors.blue,onpressed: controller != null
? () => onSetFlashModeButtonpressed(FlashMode.torch)
: null,);
}
Widget _exposureModeControlRowWidget() {
final ButtonStyle styleAuto = TextButton.styleFrom(
primary: controller?.value.exposureMode == ExposureMode.auto
? Colors.orange
: Colors.blue,);
final ButtonStyle styleLocked = TextButton.styleFrom(
primary: controller?.value.exposureMode == ExposureMode.locked
? Colors.orange
: Colors.blue,);
return SizeTransition(
sizefactor: _exposureModeControlRowAnimation,child: ClipRect(
child: Container(
color: Colors.grey.shade50,child: Column(
children: [
Center(
child: Text("Exposure Mode"),Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: [
TextButton(
child: Text('AUTO'),style: styleAuto,onpressed: controller != null
? () =>
onSetExposureModeButtonpressed(ExposureMode.auto)
: null,onLongPress: () {
if (controller != null) {
controller!.setExposurePoint(null);
showInSnackBar('Resetting exposure point');
}
},TextButton(
child: Text('LOCKED'),style: styleLocked,onpressed: controller != null
? () =>
onSetExposureModeButtonpressed(ExposureMode.locked)
: null,Center(
child: Text("Exposure Offset"),children: [
Text(_minAvailableExposureOffset.toString()),Slider(
value: _currentExposureOffset,min: _minAvailableExposureOffset,max: _maxAvailableExposureOffset,label: _currentExposureOffset.toString(),onChanged: _minAvailableExposureOffset ==
_maxAvailableExposureOffset
? null
: setExposureOffset,Text(_maxAvailableExposureOffset.toString()),);
}
Widget _focusModeControlRowWidget() {
final ButtonStyle styleAuto = TextButton.styleFrom(
primary: controller?.value.focusMode == FocusMode.auto
? Colors.orange
: Colors.blue,);
final ButtonStyle styleLocked = TextButton.styleFrom(
primary: controller?.value.focusMode == FocusMode.locked
? Colors.orange
: Colors.blue,);
return SizeTransition(
sizefactor: _focusModeControlRowAnimation,child: Column(
children: [
Center(
child: Text("Focus Mode"),onpressed: controller != null
? () => onSetFocusModeButtonpressed(FocusMode.auto)
: null,onLongPress: () {
if (controller != null) controller!.setFocusPoint(null);
showInSnackBar('Resetting focus point');
},onpressed: controller != null
? () => onSetFocusModeButtonpressed(FocusMode.locked)
: null,);
}
/// display the control bar with buttons to take pictures and record videos.
Widget _captureControlRowWidget() {
final CameraController? cameraController = controller;
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: <Widget>[
IconButton(
icon: const Icon(Icons.camera_alt),onpressed: cameraController != null &&
cameraController.value.isInitialized
// !cameraController.value.isRecordingVideo
? onTakePictureButtonpressed
: null,IconButton(
icon: const Icon(Icons.videocam),onpressed: cameraController != null &&
cameraController.value.isInitialized &&
!cameraController.value.isRecordingVideo
? onVideoRecordButtonpressed
: null,IconButton(
icon: cameraController != null &&
cameraController.value.isRecordingPaused
? Icon(Icons.play_arrow)
: Icon(Icons.pause),onpressed: cameraController != null &&
cameraController.value.isInitialized &&
cameraController.value.isRecordingVideo
? (cameraController.value.isRecordingPaused)
? onResumeButtonpressed
: onPauseButtonpressed
: null,IconButton(
icon: const Icon(Icons.stop),color: Colors.red,onpressed: cameraController != null &&
cameraController.value.isInitialized &&
cameraController.value.isRecordingVideo
? onStopButtonpressed
: null,)
],);
}
/// display a row of toggle to select the camera (or a message if no camera is available).
Widget _cameraTogglesRowWidget() {
final List<Widget> toggles = <Widget>[];
final onChanged = (CameraDescription? description) {
if (description == null) {
return;
}
onNewCameraSelected(description);
};
if (cameras.isEmpty) {
return const Text('No camera found');
} else {
for (CameraDescription cameraDescription in cameras) {
toggles.add(
SizedBox(
width: 90.0,child: RadioListTile<CameraDescription>(
title: Icon(getCameraLensIcon(cameraDescription.lensDirection)),groupValue: controller?.description,value: cameraDescription,onChanged:
controller != null && controller!.value.isRecordingVideo
? null
: onChanged,);
}
}
return Row(children: toggles);
}
String timestamp() => DateTime.Now().millisecondsSinceEpoch.toString();
void showInSnackBar(String message) {
// ignore: deprecated_member_use
_scaffoldKey.currentState?.showSnackBar(SnackBar(content: Text(message)));
}
void onViewFinderTap(TapDownDetails details,BoxConstraints constraints) {
if (controller == null) {
return;
}
final CameraController cameraController = controller!;
final offset = Offset(
details.localPosition.dx / constraints.maxWidth,details.localPosition.dy / constraints.maxHeight,);
cameraController.setExposurePoint(offset);
cameraController.setFocusPoint(offset);
}
void onNewCameraSelected(CameraDescription cameraDescription) async {
if (controller != null) {
await controller!.dispose();
}
final CameraController cameraController = CameraController(
cameraDescription,ResolutionPreset.medium,enableAudio: enableAudio,imageFormatGroup: ImageFormatGroup.jpeg,);
controller = cameraController;
// If the controller is updated then update the UI.
cameraController.addListener(() {
if (mounted) setState(() {});
if (cameraController.value.hasError) {
showInSnackBar(
'Camera error ${cameraController.value.errorDescription}');
}
});
try {
await cameraController.initialize();
await Future.wait([
cameraController
.getminexposureOffset()
.then((value) => _minAvailableExposureOffset = value),cameraController
.getMaxExposureOffset()
.then((value) => _maxAvailableExposureOffset = value),cameraController
.getMaxZoomLevel()
.then((value) => _maxAvailableZoom = value),cameraController
.getMinZoomLevel()
.then((value) => _minAvailableZoom = value),]);
} on CameraException catch (e) {
_showCameraException(e);
}
if (mounted) {
setState(() {});
}
}
void onTakePictureButtonpressed() {
takePicture().then((XFile? file) {
if (mounted) {
setState(() {
imageFile = file;
videoController?.dispose();
videoController = null;
controller?.value.flashMode == FlashMode.torch;
});
if (file != null) showInSnackBar('Picture saved to ${file.path}');
}
});
}
void onFlashModeButtonpressed() {
if (_flashModeControlRowAnimationController.value == 1) {
_flashModeControlRowAnimationController.reverse();
} else {
_flashModeControlRowAnimationController.forward();
_exposureModeControlRowAnimationController.reverse();
_focusModeControlRowAnimationController.reverse();
}
}
void onExposureModeButtonpressed() {
if (_exposureModeControlRowAnimationController.value == 1) {
_exposureModeControlRowAnimationController.reverse();
} else {
_exposureModeControlRowAnimationController.forward();
_flashModeControlRowAnimationController.reverse();
_focusModeControlRowAnimationController.reverse();
}
}
void onFocusModeButtonpressed() {
if (_focusModeControlRowAnimationController.value == 1) {
_focusModeControlRowAnimationController.reverse();
} else {
_focusModeControlRowAnimationController.forward();
_flashModeControlRowAnimationController.reverse();
_exposureModeControlRowAnimationController.reverse();
}
}
void onAudioModeButtonpressed() {
enableAudio = !enableAudio;
if (controller != null) {
onNewCameraSelected(controller!.description);
}
}
void onCaptureOrientationLockButtonpressed() async {
if (controller != null) {
final CameraController cameraController = controller!;
if (cameraController.value.isCaptureOrientationLocked) {
await cameraController.unlockCaptureOrientation();
showInSnackBar('Capture orientation unlocked');
} else {
await cameraController.lockCaptureOrientation();
showInSnackBar(
'Capture orientation locked to ${cameraController.value.lockedCaptureOrientation.toString().split('.').last}');
}
}
}
void onSetFlashModeButtonpressed(FlashMode mode) {
setFlashMode(mode).then((_) {
if (mounted) setState(() {});
showInSnackBar('Flash mode set to ${mode.toString().split('.').last}');
});
}
void onSetExposureModeButtonpressed(ExposureMode mode) {
setExposureMode(mode).then((_) {
if (mounted) setState(() {});
showInSnackBar('Exposure mode set to ${mode.toString().split('.').last}');
});
}
void onSetFocusModeButtonpressed(FocusMode mode) {
setFocusMode(mode).then((_) {
if (mounted) setState(() {});
showInSnackBar('Focus mode set to ${mode.toString().split('.').last}');
});
}
void onVideoRecordButtonpressed() {
startVideoRecording().then((_) {
if (mounted) setState(() {});
});
}
void onStopButtonpressed() {
stopVideoRecording().then((file) {
if (mounted) setState(() {});
if (file != null) {
showInSnackBar('Video recorded to ${file.path}');
videoFile = file;
_startVideoPlayer();
}
});
}
void onPauseButtonpressed() {
pauseVideoRecording().then((_) {
if (mounted) setState(() {});
showInSnackBar('Video recording paused');
});
}
void onResumeButtonpressed() {
resumeVideoRecording().then((_) {
if (mounted) setState(() {});
showInSnackBar('Video recording resumed');
});
}
Future<void> startVideoRecording() async {
final CameraController? cameraController = controller;
if (cameraController == null || !cameraController.value.isInitialized) {
showInSnackBar('Error: select a camera first.');
return;
}
if (cameraController.value.isRecordingVideo) {
return;
}
try {
await cameraController.startVideoRecording();
} on CameraException catch (e) {
_showCameraException(e);
return;
}
}
Future<XFile?> stopVideoRecording() async {
final CameraController? cameraController = controller;
if (cameraController == null || !cameraController.value.isRecordingVideo) {
return null;
}
try {
return cameraController.stopVideoRecording();
} on CameraException catch (e) {
_showCameraException(e);
return null;
}
}
Future<void> pauseVideoRecording() async {
final CameraController? cameraController = controller;
if (cameraController == null || !cameraController.value.isRecordingVideo) {
return null;
}
try {
await cameraController.pauseVideoRecording();
} on CameraException catch (e) {
_showCameraException(e);
rethrow;
}
}
Future<void> resumeVideoRecording() async {
final CameraController? cameraController = controller;
if (cameraController == null || !cameraController.value.isRecordingVideo) {
return null;
}
try {
await cameraController.resumeVideoRecording();
} on CameraException catch (e) {
_showCameraException(e);
rethrow;
}
}
Future<void> setFlashMode(FlashMode mode) async {
if (controller == null) {
return;
}
try {
await controller!.setFlashMode(mode);
} on CameraException catch (e) {
_showCameraException(e);
rethrow;
}
}
Future<void> setExposureMode(ExposureMode mode) async {
if (controller == null) {
return;
}
try {
await controller!.setExposureMode(mode);
} on CameraException catch (e) {
_showCameraException(e);
rethrow;
}
}
Future<void> setExposureOffset(double offset) async {
if (controller == null) {
return;
}
setState(() {
_currentExposureOffset = offset;
});
try {
offset = await controller!.setExposureOffset(offset);
} on CameraException catch (e) {
_showCameraException(e);
rethrow;
}
}
Future<void> setFocusMode(FocusMode mode) async {
if (controller == null) {
return;
}
try {
await controller!.setFocusMode(mode);
} on CameraException catch (e) {
_showCameraException(e);
rethrow;
}
}
Future<void> _startVideoPlayer() async {
if (videoFile == null) {
return;
}
final VideoPlayerController vController =
VideoPlayerController.file(File(videoFile!.path));
videoPlayerListener = () {
if (videoController != null && videoController!.value.size != null) {
// Refreshing the state to update video player with the correct ratio.
if (mounted) setState(() {});
videoController!.removeListener(videoPlayerListener!);
}
};
vController.addListener(videoPlayerListener!);
await vController.setLooping(true);
await vController.initialize();
await videoController?.dispose();
if (mounted) {
setState(() {
imageFile = null;
videoController = vController;
});
}
await vController.play();
}
Future<XFile?> takePicture() async {
final CameraController? cameraController = controller;
if (cameraController == null || !cameraController.value.isInitialized) {
showInSnackBar('Error: select a camera first.');
return null;
}
if (cameraController.value.isTakingPicture) {
return null;
}
try {
XFile file = await cameraController.takePicture();
return file;
} on CameraException catch (e) {
_showCameraException(e);
return null;
}
}
void _showCameraException(CameraException e) {
logError(e.code,e.description);
showInSnackBar('Error: ${e.code}\n${e.description}');
}
}
class CameraApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: CameraExampleHome(),);
}
}
List<CameraDescription> cameras = [];
Future<void> main() async {
try {
WidgetsFlutterBinding.ensureInitialized();
cameras = await availableCameras();
} on CameraException catch (e) {
logError(e.code,e.description);
}
runApp(CameraApp());
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。