Reputation: 241
So I am building a camera app, and currently, when I click the button in my bottom navigation, it opens the camera preview which has a button to take the photo.
When that button is clicked, it then goes and opens the native camera, instead of taking a photo.
I believe I have pinpointed the error here:
onPressed: () {
_openGallery();
Navigator.pop(context);
within this block
Widget _cameraControlWidget(context) {
return Expanded(
child: Align(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
FloatingActionButton(
child: Icon(
Icons.camera,
color: Colors.black,
),
backgroundColor: Colors.white,
onPressed: () {
_openGallery();
Navigator.pop(context);
},
)
],
),
),
);
}
Is this correct? How can I rectify so that the 'camera preview' takes the photo, and not the native camera?
Here is the full page code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:camera/camera.dart';
class Camera extends StatefulWidget {
Function setData;
Camera({Key key, this.setData}) : super(key: key);
@override
_CameraScreenState createState() => _CameraScreenState();
}
class _CameraScreenState extends State<Camera> {
CameraController controller;
List cameras;
int selectedCameraIndex;
String imgPath;
var image;
Future _openGallery() async {
image = await ImagePicker.pickImage(source: ImageSource.camera);
if (widget.setData != null) {
widget.setData(image);
}
}
@override
void initState() {
super.initState();
availableCameras().then((availableCameras) {
cameras = availableCameras;
if (cameras.length > 0) {
setState(() {
selectedCameraIndex = 0;
});
_initCameraController(cameras[selectedCameraIndex]).then((void v) {});
} else {
print('No camera available');
}
}).catchError((err) {
print('Error :${err.code}Error message : ${err.message}');
});
}
Future _initCameraController(CameraDescription cameraDescription) async {
if (controller != null) {
await controller.dispose();
}
controller = CameraController(cameraDescription, ResolutionPreset.high);
controller.addListener(() {
if (mounted) {
setState(() {});
}
if (controller.value.hasError) {
print('Camera error ${controller.value.errorDescription}');
}
});
try {
await controller.initialize();
} on CameraException catch (e) {
_showCameraException(e);
}
if (mounted) {
setState(() {});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
flex: 1,
child: _cameraPreviewWidget(),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: 120,
width: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
_cameraToggleRowWidget(),
_cameraControlWidget(context),
Spacer()
],
),
),
)
],
),
),
),
);
}
/// Display Camera preview.
Widget _cameraPreviewWidget() {
if (controller == null || !controller.value.isInitialized) {
return const Text(
'Loading',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.w900,
),
);
}
return AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: CameraPreview(controller),
);
}
/// Display the control bar with buttons to take pictures
Widget _cameraControlWidget(context) {
return Expanded(
child: Align(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
FloatingActionButton(
child: Icon(
Icons.camera,
color: Colors.black,
),
backgroundColor: Colors.white,
onPressed: () {
_openGallery();
Navigator.pop(context);
},
)
],
),
),
);
}
/// Display a row of toggle to select the camera (or a message if no camera is available).
Widget _cameraToggleRowWidget() {
if (cameras == null || cameras.isEmpty) {
return Spacer();
}
CameraDescription selectedCamera = cameras[selectedCameraIndex];
CameraLensDirection lensDirection = selectedCamera.lensDirection;
return Expanded(
child: Align(
alignment: Alignment.centerLeft,
child: FlatButton.icon(
onPressed: _onSwitchCamera,
icon: Icon(
_getCameraLensIcon(lensDirection),
color: Colors.white,
size: 24,
),
label: Text(
'${lensDirection.toString().substring(lensDirection.toString().indexOf('.') + 1).toUpperCase()}',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.w500),
),
),
),
);
}
IconData _getCameraLensIcon(CameraLensDirection direction) {
switch (direction) {
case CameraLensDirection.back:
return CupertinoIcons.switch_camera;
case CameraLensDirection.front:
return CupertinoIcons.switch_camera_solid;
case CameraLensDirection.external:
return Icons.camera;
default:
return Icons.device_unknown;
}
}
void _showCameraException(CameraException e) {
String errorText = 'Error:${e.code}\nError message : ${e.description}';
print(errorText);
}
void _onSwitchCamera() {
selectedCameraIndex =
selectedCameraIndex < cameras.length - 1 ? selectedCameraIndex + 1 : 0;
CameraDescription selectedCamera = cameras[selectedCameraIndex];
_initCameraController(selectedCamera);
}
}
Edit:
Here is my page which displays the photos:
import 'dart:io';
import 'package:flutter/material.dart';
class Homepage_1 extends StatefulWidget {
final List<File> imageArray;
Homepage_1({Key key, this.imageArray}) : super(key: key);
@override
_Homepage_1State createState() => _Homepage_1State();
}
class _Homepage_1State extends State<Homepage_1> {
var image;
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.white,
body: Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
Padding(
padding:
const EdgeInsets.only(top: 100, left: 40, right: 0, bottom: 0),
child:
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(
'Stumble',
style: TextStyle(
fontSize: 60,
fontFamily: 'Avenir',
fontWeight: FontWeight.w900,
),
),
Container(
margin:
EdgeInsets.only(top: 0, left: 0, right: 50, bottom: 0),
child: widget.imageArray.isEmpty
? Column(children: [
Text(
'Yikes! You have no photos',
style: TextStyle(
fontSize: 19,
fontFamily: 'Avenir',
fontWeight: FontWeight.w900,
),
),
Text(
'Click the circular button below',
style: TextStyle(
fontSize: 15,
fontFamily: 'Avenir',
fontWeight: FontWeight.w500,
),
),
])
: GridView.count(
shrinkWrap: true,
crossAxisCount: 2,
crossAxisSpacing: 25,
mainAxisSpacing: 25,
childAspectRatio: (80 / 150),
padding: const EdgeInsets.all(2.0),
children:
List.generate(widget.imageArray.length, (index) {
return ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image.file(widget.imageArray[index],
fit: BoxFit.fill),
);
})))
]),
)
]));
}
}
Upvotes: 0
Views: 2184
Reputation: 2670
I am assuming you are using from this example
https://flutter.dev/docs/cookbook/plugins/picture-using-camera
Here is full code that I just tested
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 {
final CameraDescription camera;
const TakePictureScreen({
Key key,
@required this.camera,
}) : super(key: key);
@override
TakePictureScreenState createState() => TakePictureScreenState();
}
class TakePictureScreenState extends State<TakePictureScreen> {
CameraController _controller;
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: Text('Take a picture')),
// 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 Center(child: CircularProgressIndicator());
}
},
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.camera_alt),
// 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 the picture was taken, display it on a new screen.
Navigator.push(
context,
MaterialPageRoute(
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);
}
},
),
);
}
}
// A widget that displays the picture taken by the user.
class DisplayPictureScreen extends StatelessWidget {
final String imagePath;
const DisplayPictureScreen({Key key, this.imagePath}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: 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)),
);
}
}
in pubspec.yaml
dependencies:
flutter:
sdk: flutter
camera: ^0.8.1
path_provider:
path:
Upvotes: 1