Skip to content

Instantly share code, notes, and snippets.

@Alvarocda
Last active August 4, 2023 21:15
Show Gist options
  • Save Alvarocda/40c64333cbd93d33158a0d62ae133bec to your computer and use it in GitHub Desktop.
Save Alvarocda/40c64333cbd93d33158a0d62ae133bec to your computer and use it in GitHub Desktop.
import 'package:camera/camera.dart';
import 'package:camera_example/camera_screen_controller.dart';
import 'package:flutter/material.dart';
///
///
///
class CameraScreen extends StatefulWidget {
///
///
///
const CameraScreen({Key? key}) : super(key: key);
///
///
///
@override
_CameraScreenState createState() => _CameraScreenState();
}
///
///
///
class _CameraScreenState extends State<CameraScreen> with WidgetsBindingObserver {
late final CameraScreenController _controller = CameraScreenController(context: context);
///
///
///
@override
Widget build(BuildContext context) {
return FutureBuilder<void>(
future: _controller.initializeCamera(),
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return const Scaffold(
body: Text('Loading camera'),
);
}
if (snapshot.hasError) {
return Scaffold(
appBar: AppBar(
title: const Text('Gravação'),
),
body: const Center(
child: Text(
'Failed to load camera.',
textAlign: TextAlign.center,
),
),
);
}
return Scaffold(
backgroundColor: Colors.black,
body: Stack(
alignment: Alignment.bottomCenter,
children: <Widget>[
ValueListenableBuilder<CameraLensDirection>(
valueListenable: _controller.activeCamera,
builder: (
BuildContext context,
CameraLensDirection value,
Widget? child,
) {
return CameraPreview(_controller.cameraController!);
},
),
Container(
padding: const EdgeInsets.all(16),
color: Colors.black38,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_toggleFlash(),
_startStopRecordButton(),
_toggleCameraButton(),
],
),
],
),
),
],
),
);
},
);
}
///
///
///
Widget _toggleFlash() {
return InkWell(
onTap: _controller.toggleFlash,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
color: Colors.white,
child: Container(
height: 65,
width: 65,
child: ValueListenableBuilder<FlashMode>(
valueListenable: _controller.flashMode,
builder: (
BuildContext context,
FlashMode flashMode,
Widget? child,
) {
return Icon(
flashMode == FlashMode.off ? Icons.flash_off : Icons.flash_on,
size: 35,
);
},
),
),
),
);
}
///
///
///
Widget _toggleCameraButton() {
return InkWell(
onTap: _controller.toggleCamera,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
color: Colors.white,
child: Container(
height: 65,
width: 65,
child: const Icon(
Icons.switch_camera,
size: 35,
),
),
),
);
}
///
///
///
Widget _startStopRecordButton() {
return InkWell(
onTap: _controller.startStopRecord,
child: ValueListenableBuilder<bool>(
valueListenable: _controller.recording,
builder: (BuildContext context, bool value, Widget? child) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
color: value ? Colors.white : Colors.red,
child: Container(
height: 95,
width: 95,
child: Icon(
value ? Icons.stop : Icons.play_arrow,
color: value ? Colors.black : Colors.white,
),
),
);
},
),
);
}
///
///
///
@override
void dispose() {
_controller.dispose();
super.dispose();
}
///
///
///
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
CameraController cameraController = _controller.cameraController!;
if (!cameraController.value.isInitialized) {
return;
}
if (state == AppLifecycleState.inactive) {
cameraController.dispose();
} else if (state == AppLifecycleState.resumed) {
_controller.initializeCamera(cameraDescription: cameraController.description);
}
}
}
import 'dart:async';
import 'package:camera/camera.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
///
///
///
class CameraScreenController {
final BuildContext context;
CameraController? cameraController;
List<CameraDescription>? _availableCameras;
final ValueNotifier<CameraLensDirection> activeCamera = ValueNotifier<CameraLensDirection>(CameraLensDirection.back);
final ValueNotifier<Duration> recordDuration = ValueNotifier<Duration>(Duration.zero);
final ValueNotifier<bool> recording = ValueNotifier<bool>(false);
Timer? _timerGravacao;
final ValueNotifier<FlashMode> flashMode = ValueNotifier<FlashMode>(FlashMode.off);
///
///
///
CameraScreenController({
required this.context,
});
///
///
///
Future<void> initializeCamera({CameraDescription? cameraDescription}) async {
_availableCameras ??= await availableCameras();
cameraController = CameraController(
cameraDescription ?? _availableCameras!.first,
ResolutionPreset.medium,
imageFormatGroup: ImageFormatGroup.jpeg,
);
await cameraController!.initialize();
if (!kIsWeb) {
await cameraController!.setFlashMode(FlashMode.off);
}
cameraController!.addListener(() {
recording.value = cameraController!.value.isRecordingVideo;
});
}
///
///
///
Future<void> toggleFlash() async {
if (cameraController!.value.flashMode == FlashMode.always) {
await cameraController!.setFlashMode(FlashMode.off);
} else {
await cameraController!.setFlashMode(FlashMode.always);
}
flashMode.value = cameraController!.value.flashMode;
}
///
///
///
Future<void> toggleCamera() async {
if (!recording.value) {
CameraLensDirection camera = activeCamera.value;
if (activeCamera.value == CameraLensDirection.back) {
await initializeCamera(cameraDescription: _availableCameras!.last);
camera = _availableCameras!.last.lensDirection;
} else {
await initializeCamera(cameraDescription: _availableCameras!.first);
camera = _availableCameras!.first.lensDirection;
}
activeCamera.value = camera;
}
}
///
///
///
Future<void> startStopRecord() async {
recording.value = cameraController!.value.isRecordingVideo;
if (recording.value) {
XFile xfile = await cameraController!.stopVideoRecording();
_timerGravacao?.cancel();
Navigator.of(context).pop(xfile);
} else {
await cameraController!.startVideoRecording();
int miliSegundos = 0;
_timerGravacao = Timer.periodic(const Duration(milliseconds: 100), (Timer timer) {
miliSegundos += 100;
recordDuration.value = Duration(milliseconds: miliSegundos);
});
}
}
///
///
///
void dispose() {
cameraController?.dispose();
_timerGravacao?.cancel();
recording.dispose();
recordDuration.dispose();
flashMode.dispose();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment