In the last blog post, I show how to take a picture in Flutter using the camera package. In this blog post, I will dive deeper into the camera by explaining how to turn the flash modus on and off!
I will start this example with the result of the previous blog post. In that blog post, I describe all steps necessary to show the camera’s preview and take a picture. One of the steps is to initialize the controller with the first camera. This controller has the following method to change the flash mode:
cameraController.setFlashMode(FlashMode.always);
There are different options to provide here. Besides on, and off there is also an option to set the flash mode to auto or torch. For my own example, I will toggle between the off and always modus.
/// The possible flash modes that can be set for a camera
enum FlashMode {
/// Do not use the flash when taking a picture.
off,
/// Let the device decide whether to flash the camera when taking a picture.
auto,
/// Always use the flash when taking a picture.
always,
/// Turns on the flash light and keeps it on until switched off.
torch,
}
So I know which method to call. Since I also want to change the icon, I will make the Widget a StatefulWidget. This way, I can change the icon after pressing the button. I provide the Widget with the controller directly, but it is also possible to provide the Widget with a Callback function.
The Widget is simply a button, and when the user presses the button I call the method to change the modus of the flash. Furthermore, I change the local variable to switch to a different icon. I did not find a way (yet) to extract the current flash modus from the controller. Otherwise, you could listen to the result of the setFlashMode before calling the setState method.
class CameraFlashWidget extends StatefulWidget {
final CameraController cameraController;
const CameraFlashWidget({Key? key, required this.cameraController}) : super(key: key);
@override
State<CameraFlashWidget> createState() => _CameraFlashWidgetState();
}
class _CameraFlashWidgetState extends State<CameraFlashWidget> {
FlashMode flashMode = FlashMode.off;
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: FloatingActionButton(onPressed: () {
setState(() {
if (flashMode == FlashMode.off) {
widget.cameraController.setFlashMode(FlashMode.always);
flashMode = FlashMode.always;
} else {
widget.cameraController.setFlashMode(FlashMode.off);
flashMode = FlashMode.off;
}
});
}, child: flashMode == FlashMode.off ? const Icon(Icons.flashlight_off) : const Icon(Icons.flashlight_on)),
),
],
),
],
);
}
}
Finally, all I need to do is to add the Widget in a Stacked Widget to make sure the button is visible above the preview. Another option is to make the preview smaller and change the placements of the buttons yourself.
Stack(
children: [
SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: CameraPreview(controller!),
),
CameraFlashWidget(
cameraController: controller,
),
],
)
These steps are all that is necessary to change the flash modus of the camera! All of is this is possible thanks to the work of a lot of people on the camera package! The code of this example is available here on Github. If you still have any questions, comments, suggestions, remarks, please let me know!