camerawesome 0.0.1 copy "camerawesome: ^0.0.1" to clipboard
camerawesome: ^0.0.1 copied to clipboard

outdated

An open source camera plugin by the community for the community

example/lib/main.dart

import 'dart:async';
import 'dart:io';
import 'dart:math';

import 'package:camerawesome/models/orientations.dart';
import 'package:camerawesome_example/utils/orientation_utils.dart';
import 'package:camerawesome_example/widgets/camera_buttons.dart';
import 'package:camerawesome_example/widgets/take_photo_button.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:ui' as ui;
import 'package:image/image.dart' as imgUtils;

import 'package:path_provider/path_provider.dart';
import 'package:camerawesome/camerawesome_plugin.dart';

void main() {
  runApp(MaterialApp(
    home: MyApp(),
    debugShowCheckedModeBanner: false,
  ));
}

class MyApp extends StatefulWidget {

  // just for E2E test. if true we create our images names from datetime.
  // Else it's just a name to assert image exists
  final bool randomPhotoName;

  MyApp({this.randomPhotoName = true});

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with TickerProviderStateMixin {

  double bestSizeRatio;

  String _lastPhotoPath;

  bool focus = false;

  bool fullscreen = true;

  ValueNotifier<CameraFlashes> switchFlash = ValueNotifier(CameraFlashes.NONE);

  // TODO: Add zoom smooth animation
  ValueNotifier<double> zoomNotifier = ValueNotifier(0);

  ValueNotifier<Size> photoSize = ValueNotifier(null);

  ValueNotifier<Sensors> sensor = ValueNotifier(Sensors.BACK);

  /// use this to call a take picture
  PictureController _pictureController = new PictureController();

  /// list of available sizes
  List<Size> availableSizes;

  AnimationController _iconsAnimationController;

  AnimationController _previewAnimationController;

  Animation<Offset> _previewAnimation;

  bool animationPlaying = false;

  Timer _previewDismissTimer;

  ValueNotifier<CameraOrientations> _orientation = ValueNotifier(CameraOrientations.PORTRAIT_UP);

  @override
  void initState() {
    super.initState();
    _iconsAnimationController = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 300),
    )..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          animationPlaying = false;
        }
      });

    _previewAnimationController = AnimationController(
      duration: const Duration(milliseconds: 1300),
      vsync: this,
    );
    _previewAnimation = Tween<Offset>(
      begin: const Offset(-2.0, 0.0),
      end: Offset.zero,
    ).animate(CurvedAnimation(
        parent: _previewAnimationController,
        curve: Curves.elasticOut,
        reverseCurve: Curves.elasticIn));
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
  }

  @override
  void dispose() {
    _iconsAnimationController.dispose();
    _previewAnimationController.dispose();
    photoSize.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    Alignment alignment;
    bool mirror;
    switch (_orientation.value) {
      case CameraOrientations.PORTRAIT_UP:
      case CameraOrientations.PORTRAIT_DOWN:
        alignment = _orientation.value == CameraOrientations.PORTRAIT_UP
            ? Alignment.bottomLeft
            : Alignment.topLeft;
        mirror = _orientation.value == CameraOrientations.PORTRAIT_DOWN;
        break;
      case CameraOrientations.LANDSCAPE_LEFT:
      case CameraOrientations.LANDSCAPE_RIGHT:
        alignment = Alignment.topLeft;
        mirror = _orientation.value == CameraOrientations.LANDSCAPE_LEFT;
        break;
    }

    return Scaffold(
      body: Stack(
      fit: StackFit.expand,
      children: <Widget>[
        fullscreen ? buildFullscreenCamera() : buildSizedScreenCamera(),
        _buildInterface(),
        Align(
          alignment: alignment,
          child: Padding(
            padding: OrientationUtils.isOnPortraitMode(_orientation.value)
                ? EdgeInsets.symmetric(horizontal: 35.0, vertical: 140)
                : EdgeInsets.symmetric(vertical: 65.0),
            child: Transform.rotate(
              angle: OrientationUtils.convertOrientationToRadian(
                _orientation.value,
              ),
              child: Transform(
                alignment: Alignment.center,
                transform: Matrix4.rotationY(mirror ? pi : 0.0),
                child: Dismissible(
                  onDismissed: (direction) {},
                  key: UniqueKey(),
                  child: SlideTransition(
                    position: _previewAnimation,
                    child: _buildPreviewPicture(reverseImage: mirror),
                  ),
                ),
              ),
            ),
          ),
        ),

      ],
    ));
  }

  Widget _buildPreviewPicture({bool reverseImage = false}) {
    return Container(
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.all(
          Radius.circular(15),
        ),
        boxShadow: [
          BoxShadow(
            color: Colors.black45,
            offset: Offset(2, 2),
            blurRadius: 25,
          ),
        ],
      ),
      child: Padding(
        padding: const EdgeInsets.all(3.0),
        child: ClipRRect(
          borderRadius: BorderRadius.circular(13.0),
          child: _lastPhotoPath != null
              ? Transform(
                  alignment: Alignment.center,
                  transform: Matrix4.rotationY(reverseImage ? pi : 0.0),
                  child: Image.file(
                    new File(_lastPhotoPath),
                    width: OrientationUtils.isOnPortraitMode(_orientation.value)
                        ? 128
                        : 256,
                  ),
                )
              : Container(
                  width: OrientationUtils.isOnPortraitMode(_orientation.value)
                      ? 128
                      : 256,
                  height: 228,
                  decoration: BoxDecoration(
                    color: Colors.black38,
                  ),
                  child: Center(
                    child: Icon(
                      Icons.photo,
                      color: Colors.white,
                    ),
                  ),
                ), // TODO: Placeholder here
        ),
      ),
    );
  }

  Widget _buildInterface() {
    return SafeArea(
      child: Stack(
        children: <Widget>[
          _buildTopBar(),
          _buildBottomBar(),
        ],
      ),
    );
  }

  Widget _buildTopBar() {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 16),
      child: Column(
        children: <Widget>[
          Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.only(right: 24.0),
                child: IconButton(
                  icon: Icon(
                    fullscreen ? Icons.fullscreen_exit : Icons.fullscreen,
                    color: Colors.white),
                  onPressed: () => setState(() => fullscreen = !fullscreen),
                ),
              ),
              Padding(
                padding: const EdgeInsets.only(right: 24),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    if (photoSize.value != null)
                      FlatButton(
                        key: ValueKey("resolutionButton"),
                        onPressed: _buildChangeResolutionDialog,
                        child: Text(
                          '${photoSize.value.width.toInt()} / ${photoSize.value.height.toInt()}',
                          key: ValueKey("resolutionTxt"),
                          style: TextStyle(color: Colors.white),
                        ),
                      ),
                  ],
                ),
              ),
              OptionButton(
                icon: Icons.switch_camera,
                rotationController: _iconsAnimationController,
                orientation: _orientation,
                onTapCallback: () async {
                  this.focus = !focus;
                  if (sensor.value == Sensors.FRONT) {
                    sensor.value = Sensors.BACK;
                  } else {
                    sensor.value = Sensors.FRONT;
                  }
                },
              ),
              SizedBox(
                width: 20.0,
              ),
              OptionButton(
                rotationController: _iconsAnimationController,
                icon: _getFlashIcon(),
                orientation: _orientation,
                onTapCallback: () {
                  switch(switchFlash.value) {
                    case CameraFlashes.NONE:
                      switchFlash.value = CameraFlashes.ON;
                      break;
                    case CameraFlashes.ON:
                      switchFlash.value = CameraFlashes.AUTO;
                      break;
                    case CameraFlashes.AUTO:
                      switchFlash.value = CameraFlashes.ALWAYS;
                      break;
                    case CameraFlashes.ALWAYS:
                      switchFlash.value = CameraFlashes.NONE;
                      break;
                  }
                  setState(() {});
                },
              ),
            ],
          ),
        ],
      ),
    );
  }

  IconData _getFlashIcon() {
    switch(switchFlash.value) {
      case CameraFlashes.NONE:
        return Icons.flash_off;
      case CameraFlashes.ON:
        return Icons.flash_on;
      case CameraFlashes.AUTO:
        return Icons.flash_auto;
      case CameraFlashes.ALWAYS:
        return Icons.highlight;
      default:
        return Icons.flash_off;
    }
  }

  Widget _buildBottomBar() {
    return Align(
      alignment: Alignment.bottomCenter,
      child: Padding(
        padding: const EdgeInsets.only(bottom: 32.0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: <Widget>[
            OptionButton(
              icon: Icons.zoom_out,
              rotationController: _iconsAnimationController,
              orientation: _orientation,
              onTapCallback: () {
                if (zoomNotifier.value >= 0.1) {
                  zoomNotifier.value -= 0.1;
                }
                setState(() {});
              },
            ),
            TakePhotoButton(
              key: ValueKey("takePhotoButton"),
              onTap: () async {
                final Directory extDir = await getTemporaryDirectory();
                var testDir = await Directory('${extDir.path}/test')
                    .create(recursive: true);
                final String filePath = widget.randomPhotoName ? '${testDir.path}/${DateTime.now().millisecondsSinceEpoch}.jpg' : '${testDir.path}/photo_test.jpg';
                await _pictureController.takePicture(filePath);
                // lets just make our phone vibrate
                HapticFeedback.mediumImpact();
                setState(() {
                  _lastPhotoPath = filePath;
                });
                if(_previewAnimationController.status == AnimationStatus.completed) {
                  _previewAnimationController.reset();
                }
                _previewAnimationController.forward();
                print("----------------------------------");
                print("TAKE PHOTO CALLED");
                var file = File(filePath);
                print("==> hastakePhoto : ${file.exists()}");
                print("==> path : $filePath");
                var img = imgUtils.decodeImage(file.readAsBytesSync());
                print("==> img.width : ${img.width}");
                print("==> img.height : ${img.height}");
                print("----------------------------------");
              },
            ),
            OptionButton(
              icon: Icons.zoom_in,
              rotationController: _iconsAnimationController,
              orientation: _orientation,
              onTapCallback: () {
                if (zoomNotifier.value <= 0.9) {
                  zoomNotifier.value += 0.1;
                }
                setState(() {});
              },
            ),
          ],
        ),
      ),
    );
  }

  _buildChangeResolutionDialog() {
    showModalBottomSheet(
      context: context,
      builder: (context) =>
        ListView.separated(
          itemBuilder: (context, index) =>
            ListTile(
              key: ValueKey("resOption"),
              onTap: () {
                setState(() {
                  this.photoSize.value = availableSizes[index];
                  Navigator.of(context).pop();
                });
              },
              leading: Icon(Icons.aspect_ratio),
              title: Text("${availableSizes[index].width}/${availableSizes[index].height}"),
            ),
          separatorBuilder: (context, index) => Divider(),
          itemCount: availableSizes.length
        ));
  }

  _onOrientationChange(CameraOrientations newOrientation) {
    _orientation.value = newOrientation;
    if (_previewDismissTimer != null) {
      _previewDismissTimer.cancel();
    }
  }

  _onPermissionsResult(bool granted) {
    if (!granted) {
      AlertDialog alert = AlertDialog(
        title: Text('Error'),
        content: Text(
            'It seems you doesn\'t authorized some permissions. Please check on your settings and try again.'),
        actions: [
          FlatButton(
            child: Text('OK'),
            onPressed: () => Navigator.of(context).pop(),
          ),
        ],
      );

      // show the dialog
      showDialog(
        context: context,
        builder: (BuildContext context) {
          return alert;
        },
      );
    } else {
      setState(() {});
      print("granted");
    }
  }

  Widget buildFullscreenCamera() {
    return Positioned(
        top: 0,
        left: 0,
        bottom: 0,
        right: 0,
        child: Center(
          child: CameraAwesome(
            onPermissionsResult: _onPermissionsResult,
            selectDefaultSize: (availableSizes) {
              this.availableSizes = availableSizes;
              return availableSizes[0];
            },
            photoSize: photoSize,
            sensor: sensor,
            switchFlashMode: switchFlash,
            zoom: zoomNotifier,
            onOrientationChanged: _onOrientationChange,
          ),
        ));
  }

  Widget buildSizedScreenCamera() {
    return Positioned(
        top: 0,
        left: 0,
        bottom: 0,
        right: 0,
        child: Container(
          color: Colors.black,
          child: Center(
            child: Container(
              height: 300,
              width: MediaQuery.of(context).size.width,
              child: CameraAwesome(
                onPermissionsResult: _onPermissionsResult,
                selectDefaultSize: (availableSizes) {
                  this.availableSizes = availableSizes;
                  return availableSizes[0];
                },
                photoSize: photoSize,
                sensor: sensor,
                fitted: true,
                switchFlashMode: switchFlash,
                zoom: zoomNotifier,
                onOrientationChanged: _onOrientationChange,
              ),
            ),
          ),
        ));
  }
}
774
likes
0
pub points
97%
popularity

Publisher

verified publisherapparence.io

An open source camera plugin by the community for the community

Homepage
Repository (GitHub)
View/report issues

License

unknown (LICENSE)

Dependencies

flutter, rxdart

More

Packages that depend on camerawesome