DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for Switching camera’s in Flutter
Bart van Wezel
Bart van Wezel

Posted on • Originally published at bartvwezel.nl on

Switching camera’s in Flutter

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 switch between the different cameras on the phone.

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. Next, the app looks up all available cameras on the phone during the start-up with the following line of code:

  cameras = await availableCameras();
Enter fullscreen mode Exit fullscreen mode

I always use the same camera description to initialize the controller. Unfortunately, this means the user cannot interact with the other cameras. So let’s change that! The first step is to add a button for each camera. You might use another approach with the increasing number of cameras new devices have, but you can use the same idea.

class CameraSelectionWidget extends StatelessWidget {
  final CameraDescription selectedCamera;

  const CameraSelectionWidget({Key? key, required this.selectedCamera}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final List<Widget> toggles = [];
    for (final CameraDescription cameraDescription in cameras) {
      toggles.add(
        Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            Container(
              child: Row(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Radio<CameraDescription>(
                    groupValue: selectedCamera,
                    value: cameraDescription,
                    onChanged: (value) {
                      //
                    },
                  ),
                  Icon(
                    getCameraLensIcon(cameraDescription.lensDirection, context),
                  ),
                ],
              ),
            )
          ],
        ),
      );
    }
    return Padding(
      padding: const EdgeInsets.all(16),
      child: Column(
        mainAxisSize: MainAxisSize.max,
        mainAxisAlignment: MainAxisAlignment.end,
        crossAxisAlignment: CrossAxisAlignment.end,
        children: toggles,
      ),
    );
  }
}

IconData getCameraLensIcon(CameraLensDirection direction, BuildContext context) {
  switch (direction) {
    case CameraLensDirection.back:
      return Icons.camera_rear;
    case CameraLensDirection.front:
      return Icons.camera_front;
    case CameraLensDirection.external:
      return Icons.camera;
  }
}
Enter fullscreen mode Exit fullscreen mode

This Widget will show all available cameras with a radio button next to them. When the camera is in use, the radio button is active. Furthermore, I determine the icon based on the direction of the camera. However, selecting another camera does not change anything yet. For this, I need to provide a callback to update the controller.

  void updateController(CameraDescription description) {
    controller?.dispose().then((value) {
      setState(() {});
      controller = CameraController(description, ResolutionPreset.max);
      controller!.initialize().then((_) {
        setState(() {});
      });
    });
  }
Enter fullscreen mode Exit fullscreen mode

Here I initialize the controller again and update the Widget when the camera is initialized. To call this method from the camera selection Widget, I need to provide the method to the Camera Selection Widget. I also wrap the preview with a Stack. This makes it possible to draw the camera selection above the preview.

Stack(
    children: [
      SizedBox(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        child: CameraPreview(controller!),
      ),
      CameraSelectionWidget(
        selectedCamera: controller!.description,
        onChanged: updateController,
      ),
    ],
    )
Enter fullscreen mode Exit fullscreen mode

To handle the function, I need to add it to the constructor method, and then I can call the method when the onchanged of the radio button is triggered.

class CameraSelectionWidget extends StatelessWidget {
  final CameraDescription selectedCamera;
  final Function(CameraDescription) onChanged;

  const CameraSelectionWidget({Key? key, required this.selectedCamera, required this.onChanged}) : super(key: key);

// and the change in the radio button:

  Radio<CameraDescription>(
    groupValue: selectedCamera,
    value: cameraDescription,
    onChanged: (value) {
      onChanged(value!);
    },
  ),
Enter fullscreen mode Exit fullscreen mode

These steps are all that is necessary to switch between cameras in a Flutter application! 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!

The post Switching camera’s in Flutter appeared first on Barttje.

Top comments (0)

We are hiring! Do you want to be our Senior Platform Engineer? Forem is hiring a Senior Platform Engineer

If you're interested in ops and site reliability and capable of dipping in to our Linux stack, we'd love your help shoring up our systems!