Tomar una foto usando la cámara
Cómo usar un plugin de cámara en dispositivos móviles.
Muchas aplicaciones requieren trabajar con las cámaras del dispositivo para
tomar fotos y videos. Flutter proporciona el plugin camera
para este propósito. El plugin camera proporciona herramientas para obtener una lista de las
cámaras disponibles, mostrar una vista previa proveniente de una cámara específica
y tomar fotos o videos.
Esta receta demuestra cómo usar el plugin camera para mostrar una vista previa,
tomar una foto y mostrarla usando los siguientes pasos:
- Añade las dependencias requeridas.
- Obtén una lista de las cámaras disponibles.
- Crea e inicializa el
CameraController. - Usa un
CameraPreviewpara mostrar la transmisión de la cámara. - Toma una foto con el
CameraController. - Muestra la foto con un Widget
Image.
1. Añade las dependencias requeridas
#Para completar esta receta, debes añadir tres dependencias a tu aplicación:
cameraProporciona herramientas para trabajar con las cámaras en el dispositivo.
path_providerEncuentra las rutas correctas para almacenar imágenes.
pathCrea rutas que funcionen en cualquier plataforma.
Para añadir los paquetes como dependencias, ejecuta flutter pub add:
flutter pub add camera path_provider path
2. Obtén una lista de las cámaras disponibles
#A continuación, obtén una lista de las cámaras disponibles usando el plugin camera.
// Ensure that plugin services are initialized so that `availableCameras()`
// can be called before `runApp()`
WidgetsFlutterBinding.ensureInitialized();
// Obtain a list of the available cameras on the device.
final cameras = await availableCameras();
// Get a specific camera from the list of available cameras.
final firstCamera = cameras.first;
3. Crea e inicializa el CameraController
#
Una vez que tengas una cámara, sigue estos pasos para
crear e inicializar un CameraController.
Este proceso establece una conexión con
la cámara del dispositivo que te permite controlar la cámara
y mostrar una vista previa de la transmisión de la cámara.
- Crea un
StatefulWidgetcon una claseStatecomplementaria. - Añade una variable a la clase
Statepara almacenar elCameraController. - Añade una variable a la clase
Statepara almacenar elFuturedevuelto porCameraController.initialize(). - Crea e inicializa el controlador en el método
initState(). - Destruye (dispose) el controlador en el método
dispose().
// A screen that allows users to take a picture using a given camera.
class TakePictureScreen extends StatefulWidget {
const TakePictureScreen({super.key, required this.camera});
final CameraDescription camera;
@override
TakePictureScreenState createState() => TakePictureScreenState();
}
class TakePictureScreenState extends State<TakePictureScreen> {
late CameraController _controller;
late Future<void> _initializeControllerFuture;
@override
void initState() {
super.initState();
// To display the current output from the Camera,
// create a CameraController.
_controller = CameraController(
// Get a specific camera from the list of available cameras.
widget.camera,
// Define the resolution to use.
ResolutionPreset.medium,
);
// Next, initialize the controller. This returns a Future.
_initializeControllerFuture = _controller.initialize();
}
@override
void dispose() {
// Dispose of the controller when the widget is disposed.
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// Fill this out in the next steps.
return Container();
}
}
4. Usa un CameraPreview para mostrar la transmisión de la cámara
#
A continuación, usa el Widget CameraPreview del paquete camera para
mostrar una vista previa de la transmisión de la cámara.
Usa un FutureBuilder
exactamente para este propósito.
// You must wait until the controller is initialized before displaying the
// camera preview. Use a FutureBuilder to display a loading spinner until the
// controller has finished initializing.
FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the Future is complete, display the preview.
return CameraPreview(_controller);
} else {
// Otherwise, display a loading indicator.
return const Center(child: CircularProgressIndicator());
}
},
)
5. Toma una foto con el CameraController
#
Puedes usar el CameraController para tomar fotos utilizando el
método takePicture(),
el cual devuelve un XFile,
una abstracción de File simplificada y multiplataforma.
Tanto en Android como en iOS, la nueva imagen se almacena en sus
respectivos directorios de caché,
y la ruta (path) a esa ubicación se devuelve en el XFile.
En este ejemplo, crea un FloatingActionButton que tome una foto
usando el CameraController cuando el usuario toque el botón.
Tomar una foto requiere 2 pasos:
- Asegúrate de que la cámara esté inicializada.
- Usa el controlador para tomar una foto y asegúrate
de que devuelva un
Future<XFile>.
Es una buena práctica envolver estas operaciones en un bloque try / catch para
manejar cualquier error que pueda ocurrir.
FloatingActionButton(
// Provide an onPressed callback.
onPressed: () async {
// Take the Picture in a try / catch block. If anything goes wrong,
// catch the error.
try {
// Ensure that the camera is initialized.
await _initializeControllerFuture;
// Attempt to take a picture and then get the location
// where the image file is saved.
final image = await _controller.takePicture();
} catch (e) {
// If an error occurs, log the error to the console.
print(e);
}
},
child: const Icon(Icons.camera_alt),
)
6. Muestra la foto con un Widget Image
#
Si tomas la foto con éxito, puedes mostrar la imagen guardada
usando un Widget Image. En este caso, la foto se almacena como un archivo en
el dispositivo.
Por lo tanto, debes proporcionar un File al constructor Image.file.
Puedes crear una instancia de la clase File pasando la ruta creada en
el paso anterior.
Image.file(File('path/to/my/picture.png'));
Ejemplo completo
#import 'dart:async';
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
Future<void> main() async {
// Ensure that plugin services are initialized so that `availableCameras()`
// can be called before `runApp()`
WidgetsFlutterBinding.ensureInitialized();
// Obtain a list of the available cameras on the device.
final cameras = await availableCameras();
// Get a specific camera from the list of available cameras.
final firstCamera = cameras.first;
runApp(
MaterialApp(
theme: ThemeData.dark(),
home: TakePictureScreen(
// Pass the appropriate camera to the TakePictureScreen widget.
camera: firstCamera,
),
),
);
}
// A screen that allows users to take a picture using a given camera.
class TakePictureScreen extends StatefulWidget {
const TakePictureScreen({super.key, required this.camera});
final CameraDescription camera;
@override
TakePictureScreenState createState() => TakePictureScreenState();
}
class TakePictureScreenState extends State<TakePictureScreen> {
late CameraController _controller;
late Future<void> _initializeControllerFuture;
@override
void initState() {
super.initState();
// To display the current output from the Camera,
// create a CameraController.
_controller = CameraController(
// Get a specific camera from the list of available cameras.
widget.camera,
// Define the resolution to use.
ResolutionPreset.medium,
);
// Next, initialize the controller. This returns a Future.
_initializeControllerFuture = _controller.initialize();
}
@override
void dispose() {
// Dispose of the controller when the widget is disposed.
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Take a picture')),
// You must wait until the controller is initialized before displaying the
// camera preview. Use a FutureBuilder to display a loading spinner until the
// controller has finished initializing.
body: FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// If the Future is complete, display the preview.
return CameraPreview(_controller);
} else {
// Otherwise, display a loading indicator.
return const Center(child: CircularProgressIndicator());
}
},
),
floatingActionButton: FloatingActionButton(
// Provide an onPressed callback.
onPressed: () async {
// Take the Picture in a try / catch block. If anything goes wrong,
// catch the error.
try {
// Ensure that the camera is initialized.
await _initializeControllerFuture;
// Attempt to take a picture and get the file `image`
// where it was saved.
final image = await _controller.takePicture();
if (!context.mounted) return;
// If the picture was taken, display it on a new screen.
await Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (context) => DisplayPictureScreen(
// Pass the automatically generated path to
// the DisplayPictureScreen widget.
imagePath: image.path,
),
),
);
} catch (e) {
// If an error occurs, log the error to the console.
print(e);
}
},
child: const Icon(Icons.camera_alt),
),
);
}
}
// A widget that displays the picture taken by the user.
class DisplayPictureScreen extends StatelessWidget {
final String imagePath;
const DisplayPictureScreen({super.key, required this.imagePath});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Display the Picture')),
// The image is stored as a file on the device. Use the `Image.file`
// constructor with the given path to display the image.
body: Image.file(File(imagePath)),
);
}
}
A menos que se indique lo contrario, la documentación de este sitio refleja Flutter 3.44.0. Página actualizada por última vez el 2026-05-05. Ver código fuente oreportar un problema.