Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class _MyHomePageState extends State<MyHomePage> {
context,
MaterialPageRoute(
builder: (_) => CameraCamera(
resolutionPreset: ResolutionPreset.ultraHigh,
onFile: (file) {
photos.add(file);
Navigator.pop(context);
Expand All @@ -53,8 +54,7 @@ class _MyHomePageState extends State<MyHomePage> {
title: Text(widget.title),
),
body: GridView.builder(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemCount: photos.length,
itemBuilder: (_, index) => Padding(
padding: const EdgeInsets.all(8.0),
Expand Down
5 changes: 3 additions & 2 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ dependencies:

# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
camera_camera: ^2.0.2
cupertino_icons: ^1.0.3
camera_camera:
path: ..

dev_dependencies:
flutter_test:
Expand Down
28 changes: 28 additions & 0 deletions lib/src/core/OrientationPreferences.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'package:flutter/services.dart';

class OrientationPreferences {
/// blocks rotation; sets orientation to: portrait
static portraitModeOnly() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
}

/// blocks rotation; sets orientation to: portrait
static landscapeModeOnly() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
}

static enableRotation() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
}
}
2 changes: 1 addition & 1 deletion lib/src/core/camera_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class CameraBloc {
final statusStream =
BehaviorSubject<CameraStatus>.seeded(CameraStatusEmpty());
CameraStatus get status =>
statusStream.valueWrapper?.value ?? CameraStatusEmpty();
statusStream.valueOrNull ?? CameraStatusEmpty();
set status(CameraStatus status) => statusStream.sink.add(status);

void init() async {
Expand Down
26 changes: 4 additions & 22 deletions lib/src/presentation/camera_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,29 +89,11 @@ class _CameraCameraState extends State<CameraCamera> {
enableZoom: widget.enableZoom,
key: UniqueKey(),
controller: controller,
onCameraChange: () {
bloc.changeCamera();
},
enableFlipCamera: (bloc.status.preview.cameras.length > 1),
),
if (bloc.status.preview.cameras.length > 1)
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.all(32.0),
child: InkWell(
onTap: () {
bloc.changeCamera();
},
child: CircleAvatar(
radius: 20,
backgroundColor: Colors.black.withOpacity(0.6),
child: Icon(
Platform.isAndroid
? Icons.flip_camera_android
: Icons.flip_camera_ios,
color: Colors.white,
),
),
),
),
)
],
),
failure: (message, _) => Container(
Expand Down
23 changes: 11 additions & 12 deletions lib/src/presentation/controller/camera_camera_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ class CameraCameraController {
required this.onPath,
this.enableAudio = false,
}) {
_controller = CameraController(cameraDescription, resolutionPreset,
enableAudio: enableAudio);
_controller = CameraController(cameraDescription, resolutionPreset, enableAudio: enableAudio);
}

void init() async {
Expand All @@ -40,14 +39,7 @@ class CameraCameraController {
await _controller.setFlashMode(FlashMode.off);
} catch (e) {}

status = CameraCameraSuccess(
camera: Camera(
maxZoom: maxZoom,
minZoom: minZoom,
zoom: minZoom,
maxExposure: maxExposure,
minExposure: minExposure,
flashMode: FlashMode.off));
status = CameraCameraSuccess(camera: Camera(maxZoom: maxZoom, minZoom: minZoom, zoom: minZoom, maxExposure: maxExposure, minExposure: minExposure, flashMode: FlashMode.off));
} on CameraException catch (e) {
status = CameraCameraFailure(message: e.description ?? "", exception: e);
}
Expand Down Expand Up @@ -98,8 +90,7 @@ class CameraCameraController {
void setZoomLevel(double zoom) async {
if (zoom != 1) {
var cameraZoom = double.parse(((zoom)).toStringAsFixed(1));
if (cameraZoom >= status.camera.minZoom &&
cameraZoom <= status.camera.maxZoom) {
if (cameraZoom >= status.camera.minZoom && cameraZoom <= status.camera.maxZoom) {
final camera = status.camera.copyWith(zoom: cameraZoom);
status = CameraCameraSuccess(camera: camera);
await _controller.setZoomLevel(cameraZoom);
Expand Down Expand Up @@ -153,4 +144,12 @@ class CameraCameraController {
await _controller.dispose();
return;
}

double aspectRatio() {
return _controller.value.aspectRatio;
}

Size? size() {
return _controller.value.previewSize;
}
}
158 changes: 110 additions & 48 deletions lib/src/presentation/widgets/camera_preview.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import 'dart:io';

import 'package:camera_camera/src/core/OrientationPreferences.dart';
import 'package:camera_camera/src/presentation/controller/camera_camera_controller.dart';
import 'package:camera_camera/src/presentation/controller/camera_camera_status.dart';
import 'package:flutter/material.dart';
Expand All @@ -6,11 +9,15 @@ class CameraCameraPreview extends StatefulWidget {
final void Function(String value)? onFile;
final CameraCameraController controller;
final bool enableZoom;
final bool enableFlipCamera;
final GestureTapCallback? onCameraChange;
CameraCameraPreview({
Key? key,
this.onFile,
required this.controller,
required this.enableZoom,
required this.enableFlipCamera,
required this.onCameraChange,
}) : super(key: key);

@override
Expand All @@ -20,6 +27,7 @@ class CameraCameraPreview extends StatefulWidget {
class _CameraCameraPreviewState extends State<CameraCameraPreview> {
@override
void initState() {
OrientationPreferences.portraitModeOnly();
widget.controller.init();
super.initState();
}
Expand All @@ -28,80 +36,134 @@ class _CameraCameraPreviewState extends State<CameraCameraPreview> {
void dispose() {
widget.controller.dispose();
super.dispose();
OrientationPreferences.enableRotation();
}

@override
Widget build(BuildContext context) {
return ValueListenableBuilder<CameraCameraStatus>(
valueListenable: widget.controller.statusNotifier,
builder: (_, status, __) => status.when(
success: (camera) => GestureDetector(
onScaleUpdate: (details) {
widget.controller.setZoomLevel(details.scale);
},
child: Stack(
children: [
Center(child: widget.controller.buildPreview()),
if (widget.enableZoom)
Positioned(
bottom: 96,
left: 0.0,
right: 0.0,
success: (camera) {
Size? size = widget.controller.size();
return GestureDetector(
onScaleUpdate: (details) {
widget.controller.setZoomLevel(details.scale);
},
child: Stack(
children: [
new OverflowBox(
maxWidth: double.infinity,
maxHeight: double.infinity,
alignment: Alignment.center,
child: new FittedBox(
fit: BoxFit.cover,
alignment: Alignment.center,
clipBehavior: Clip.hardEdge,
child: new Container(
width: size?.shortestSide,
height: size?.longestSide,
//child: AspectRatio(
//aspectRatio: widget.controller.aspectRatio(),
child: widget.controller.buildPreview(),
//),
),
),
),
Positioned(
bottom: 0,
//left: 0.0,
//right: 0.0,
child: Container(
height: 96 + 2 * 20 + 32,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.4),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
),
),
if (widget.enableZoom)
Positioned(
bottom: 96,
left: 0.0,
right: 0.0,
child: CircleAvatar(
radius: 20,
backgroundColor: Colors.grey.withOpacity(0.6),
child: IconButton(
icon: Center(
child: Text(
"${camera.zoom.toStringAsFixed(1)}x",
style: TextStyle(color: Colors.white, fontSize: 12),
),
),
onPressed: () {
widget.controller.zoomChange();
},
),
),
),
if (widget.controller.flashModes.length > 1)
Align(
alignment: Alignment.bottomLeft,
child: Padding(
padding: const EdgeInsets.all(32.0),
child: CircleAvatar(
radius: 20,
backgroundColor: Colors.black.withOpacity(0.6),
child: IconButton(
icon: Center(
child: Text(
"${camera.zoom.toStringAsFixed(1)}x",
style: TextStyle(
color: Colors.white, fontSize: 12),
),
),
onPressed: () {
widget.controller.zoomChange();
widget.controller.changeFlashMode();
},
icon: Icon(
camera.flashModeIcon,
color: Colors.white,
),
),
),
),
if (widget.controller.flashModes.length > 1)
Align(
alignment: Alignment.bottomLeft,
child: Padding(
padding: const EdgeInsets.all(32.0),
child: CircleAvatar(
radius: 20,
backgroundColor: Colors.black.withOpacity(0.6),
child: IconButton(
onPressed: () {
widget.controller.changeFlashMode();
},
icon: Icon(
camera.flashModeIcon,
color: Colors.white,
),
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.only(bottom: 24),
child: InkWell(
onTap: widget.controller.takePhoto,
child: CircleAvatar(
radius: 30,
backgroundColor: Colors.white,
),
),
),
),
if (widget.enableFlipCamera)
Align(
alignment: Alignment.bottomCenter,
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(bottom: 24),
padding: const EdgeInsets.all(32.0),
child: InkWell(
onTap: () {
widget.controller.takePhoto();
},
onTap: widget.onCameraChange,
child: CircleAvatar(
radius: 30,
backgroundColor: Colors.white,
radius: 20,
backgroundColor: Colors.black.withOpacity(0.6),
child: Icon(
Platform.isAndroid //
? Icons.flip_camera_android
: Icons.flip_camera_ios,
color: Colors.white,
),
),
),
),
),
],
),
)
],
),
);
},
failure: (message, _) => Container(
color: Colors.black,
child: Text(message),
Expand Down
6 changes: 3 additions & 3 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ environment:
sdk: ">=2.12.0-0.0 <3.0.0"

dependencies:
camera: ^0.8.0-nullsafety.2
camera: ^0.9.4+3
font_awesome_flutter: ^9.0.0-nullsafety
rxdart: ^0.26.0
rxdart: ^0.27.2
flutter:
sdk: flutter

dev_dependencies:
flutter_test:
sdk: flutter
mocktail: ^0.0.1-dev.11
mocktail: ^0.2.0

# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec
Expand Down