Skip to content

Instantly share code, notes, and snippets.

@aravindhkumar23
Last active March 19, 2021 20:44
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save aravindhkumar23/739cf778e31fa48f4f38c7494066d721 to your computer and use it in GitHub Desktop.
Save aravindhkumar23/739cf778e31fa48f4f38c7494066d721 to your computer and use it in GitHub Desktop.
Flutter Camera view with + button to open gallery (captured image and gallery picked image will be shown in horizontal scrollable view in bottom like whatsapp)
import 'dart:async';
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
import '/utils.dart';
List<CameraDescription> camerasList;
class CameraTest extends StatefulWidget {
const CameraTest({Key key}) : super(key: key);
@override
_CameraTestState createState() => new _CameraTestState();
}
class _CameraTestState extends State<CameraTest> {
CameraController controller;
List<String> imageList = <String>[];
String imagePath;
double _animatedHeight = 0.0;
String _errorMsg = '';
@override
void initState() {
super.initState();
initCamera();
}
void initCamera() async {
camerasList = await availableCameras();
controller = new CameraController(camerasList[0], ResolutionPreset.medium);
await controller.initialize();
if (mounted) {
setState(() {});
}
}
@override
void dispose() {
controller?.dispose();
super.dispose();
}
String timestamp() => new DateTime.now().millisecondsSinceEpoch.toString();
void showInSnackBar(String message) {
setState(() {
_animatedHeight = 30.0;
_errorMsg = message;
});
Future<void>.delayed(const Duration(seconds: 1), _hideErrorMsg);
}
void _hideErrorMsg() {
setState(() {
_animatedHeight = 0.0;
_errorMsg = '';
});
}
Future<String> takePicture() async {
if (!controller.value.isInitialized) {
showInSnackBar('Error: select a camera first.');
return null;
}
final bool writeAccess = await Utils.checkWritePermission();
Directory extDir;
// if user disagrees to allow storage access the use app storage
if (writeAccess) {
extDir = await getExternalStorageDirectory();
} else {
extDir = await getApplicationDocumentsDirectory();
}
final String dirPath = '${extDir.path}/Pictures/pics';
await new Directory(dirPath).create(recursive: true);
final String filePath = '$dirPath/${timestamp()}.jpg';
if (controller.value.isTakingPicture) {
// A capture is already pending, do nothing.
return null;
}
try {
await controller.takePicture(filePath);
} on CameraException catch (e) {
print('Exception -> $e');
return null;
}
setState(() {
imageList.add(filePath);
});
return filePath;
}
@override
Widget build(BuildContext context) {
if (controller == null || !controller.value.isInitialized) {
return new Container(
alignment: Alignment.center,
child: const CircularProgressIndicator(),
);
}
return new Stack(
alignment: Alignment.center,
children: <Widget>[
new AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: new CameraPreview(controller)),
new Positioned(
child: new GestureDetector(
onTap: () {
Navigator.of(context).pop();
},
child: const Icon(
Icons.close,
color: Colors.grey,
size: 30.0,
),
),
top: 30.0,
right: 10.0,
),
new Container(
child: new Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new Container(
height: 60.0,
child: new ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext c, int i) {
return Padding(
padding: const EdgeInsets.all(1.0),
child: new Image.asset(imageList[i]),
);
},
itemCount: imageList.length,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new GestureDetector(
onTap: () async {
final File galleryImagePath = await ImagePicker.pickImage(
source: ImageSource.gallery);
if (galleryImagePath != null) {
setState(() {
imageList.add(galleryImagePath);
});
}
},
child: const Padding(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 10.0),
child: const Icon(
Icons.add_box,
color: Colors.white,
size: 40.0,
),
),
),
new FlatButton(
padding: const EdgeInsets.all(10.0),
onPressed: () {
takePicture();
},
child: const Icon(
Icons.camera,
color: Colors.blue,
size: 40.0,
),
),
GestureDetector(
onTap: () {},
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 10.0),
padding: const EdgeInsets.all(8.0),
decoration: new BoxDecoration(
color: imageList.isEmpty ? Colors.grey : Colors.blue,
borderRadius: new BorderRadius.circular(40.0),
),
child: const Icon(Icons.done),
),
)
],
),
],
),
),
],
);
}
}
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:simple_permissions/simple_permissions.dart';
class Utils {
static Future<bool> checkWritePermission() async {
if(Platform.isIOS){
return false;
}
bool permission = false;
await SimplePermissions
.checkPermission(Permission.WriteExternalStorage)
.then((bool checkOkay) {
if (!checkOkay) {
SimplePermissions
.requestPermission(Permission.WriteExternalStorage)
.then((bool okDone) {
if (okDone) {
permission = true;
}
});
} else {
permission = true;
}
});
return permission;
}
}
@aravindhkumar23
Copy link
Author

aravindhkumar23 commented Aug 2, 2018

Camera view enables continuous capture of images and displayed in the horizontal list view.
Android: if write permission is given then save in external directory else save the images to app directory.
iOS: save the images to app directory.
Pub packages used
camera: "^0.2.1"
image_picker: "^0.4.5"

@pzentenoe
Copy link

Could you share the complete code please?

@loisenjoki
Copy link

Could you share the complete code please?

@aravindhkumar23
Copy link
Author

Could you share the complete code please?

I think these 2 files is enough, just do a navigator push from any button click[say simple FAB click action] to CameraTest page.

let me know if it works or else will try to share the sample application.

@Aaqib22
Copy link

Aaqib22 commented Apr 29, 2020

please share this code sir plzz aqib0002@gmail.com

@Aaqib22
Copy link

Aaqib22 commented Apr 29, 2020

sir please share complete project

@aravindhkumar23
Copy link
Author

aravindhkumar23 commented Apr 29, 2020

@Aaqib22 please find the complete source code here
I hope this will be helpful for everyone.

@neokibe
Copy link

neokibe commented May 14, 2020

Hi aravindhkumar, great project thanks, may you please assist because you used a text widget to display image path instead of the exact images

@neokibe
Copy link

neokibe commented May 14, 2020

.map((dynamic val) => new Text('\n${val.toString()}'))
This line only dispaly the image path.
How do i change this line to display images

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment