Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter - How correctly pause camera when user moved to other (preview) screen?

I need to pause camera when I move to another screen on the navigator tree in order to save battery and performance.

I tried to dispose() cameraController, but flutter doesn't re-initialize the state when it returns from another screen (which is obvious, though).

My main code to work with a camera:

 @override
  void initState() {
    super.initState();
    availableCameras().then((cameras) {
      setState(() {
        _firstCamera = cameras.first;
        _controller = CameraController(_firstCamera, ResolutionPreset.high);

        _initializeControllerFuture = _controller.initialize();
      });
    });
  }

  @override
  void dispose() {
    _controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      body: Stack(
        children: <Widget>[
          FutureBuilder<void>(
            future: _initializeControllerFuture,
            builder: (context, snapshot) {

              if (snapshot.connectionState == ConnectionState.done) {
                return Stack(
                  alignment: FractionalOffset.center,
                  children: <Widget>[
                    new Positioned.fill(
                      child: _getCameraPreview(context),
                    ),
                    ...                    
                  ],
                );
              } else {
                return Center(child: CircularProgressIndicator());
              }
            },
          ),
          Align(
            alignment: Alignment.bottomCenter,
            child: BottomAppBar(
              color: Color.fromARGB(0, 0, 0, 0),
              child: _getBottomAppBarRow(context),
            ),
          ),
        ],
      ),
    );
  }

  _getCameraPreview(BuildContext context) {
    final size = MediaQuery.of(context).size;
    final deviceRatio = size.width / size.height;
    return Transform.scale(
      scale: _controller.value.aspectRatio / deviceRatio,
      child: Center(
        child: AspectRatio(
          aspectRatio: _controller.value.aspectRatio,
          child: CameraPreview(_controller),
        ),
      ),
    );
  }
like image 223
alectogeek Avatar asked Jul 17 '19 08:07

alectogeek


People also ask

How do I change the camera preview size in flutter?

The way I solve it is very simple. return Stack( children: [ Container( width: double. infinity, height: double. infinity, child: CameraPreview(_cameraController)) ], );

How do you add a camera dependency in flutter?

To begin, we must add the required dependency, the camera package to your pubspec. yaml file. Next, we need to add permission configuration for Android and iOS. Lastly, replace the content of your main.

How do I click multiple pictures from my camera on flutter?

To select multiple images we will use image_picker flutter package. in this Package, we can select multiple images from the gallery.


1 Answers

Have a variable like _cameraOn = true. Show CameraPreview when it is true and not when it is false. While navigating to another screen set it to false

You could have the camera related functionality in a separate widget. So every time it is displayed it is initialized, and when it is not it's disposed.

A simple working example

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';

List<CameraDescription> cameras;

Future<void> main() async {
  cameras = await availableCameras();
  runApp(MaterialApp(
    home: CameraApp(),
  ));
}

class CameraApp extends StatefulWidget {
  @override
  _CameraAppState createState() => _CameraAppState();
}

class _CameraAppState extends State<CameraApp> {
  bool _cameraOn = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: <Widget>[
          Expanded(
            child: _cameraOn ? Camera() : Container(),
          ),
          FlatButton(
            onPressed: () {
              setState(() {
                _cameraOn = false;
              });
              Navigator.push(
                  context,
                  MaterialPageRoute(
                      builder: (BuildContext context) => Post())).then((res) {
                setState(() {
                  _cameraOn = true;
                });
              }).catchError((err) {
                print(err);
              });
            },
            child: Text("NEXT PAGE"),
          ),
        ],
      ),
    );
  }
}

class Camera extends StatefulWidget {
  @override
  _CameraState createState() => _CameraState();
}

class _CameraState extends State<Camera> {
  CameraController controller;

  @override
  void initState() {
    super.initState();
    controller = CameraController(cameras[0], ResolutionPreset.medium);
    controller.initialize().then((_) {
      if (!mounted) {
        return;
      }
      setState(() {});
    });
  }

  @override
  Widget build(BuildContext context) {
    if (!controller.value.isInitialized) {
      return Container();
    }

    return AspectRatio(
      aspectRatio: controller.value.aspectRatio,
      child: CameraPreview(controller),
    );
  }

  @override
  void dispose() {
    controller?.dispose();
    super.dispose();
  }
}

class Post extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Text("Post"),
    );
  }
}

like image 115
10101010 Avatar answered Oct 05 '22 04:10

10101010