From 28f8928111eb5638a7b5f169d453afe7b1abf10a Mon Sep 17 00:00:00 2001 From: alenj Date: Fri, 8 Jan 2021 10:40:23 +0530 Subject: [PATCH] CameraView.dart --- .flutter-plugins-dependencies | 1 + .idea/libraries/Dart_Packages.xml | 308 +++++++++++++++++ .idea/libraries/Dart_SDK.xml | 29 ++ .idea/modules.xml | 8 + android/app/build.gradle | 2 +- ios/Flutter/flutter_export_environment.sh | 6 +- lib/CameraView.dart | 385 ++++++++++++++++++++++ lib/insta_home.dart | 42 ++- pubspec.lock | 137 ++++++-- pubspec.yaml | 2 + 10 files changed, 881 insertions(+), 39 deletions(-) create mode 100644 .flutter-plugins-dependencies create mode 100644 .idea/libraries/Dart_Packages.xml create mode 100644 .idea/libraries/Dart_SDK.xml create mode 100644 .idea/modules.xml create mode 100644 lib/CameraView.dart diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies new file mode 100644 index 0000000..1aa7a8b --- /dev/null +++ b/.flutter-plugins-dependencies @@ -0,0 +1 @@ +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"camera","path":"C:\\\\src\\\\flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\camera-0.5.8+17\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.27\\\\","dependencies":[]}],"android":[{"name":"camera","path":"C:\\\\src\\\\flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\camera-0.5.8+17\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.27\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"C:\\\\src\\\\flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-0.0.4+8\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\src\\\\flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-0.0.1+2\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\src\\\\flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-0.0.4+3\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"camera","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2021-01-08 10:37:29.744834","version":"1.22.4"} \ No newline at end of file diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml new file mode 100644 index 0000000..b1a6453 --- /dev/null +++ b/.idea/libraries/Dart_Packages.xml @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Dart_SDK.xml b/.idea/libraries/Dart_SDK.xml new file mode 100644 index 0000000..b0c4dac --- /dev/null +++ b/.idea/libraries/Dart_SDK.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..e4cdc64 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index ec59e3c..4e966e1 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -24,7 +24,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.flutterinstaclone" - minSdkVersion 16 + minSdkVersion 21 targetSdkVersion 27 versionCode 1 versionName "1.0" diff --git a/ios/Flutter/flutter_export_environment.sh b/ios/Flutter/flutter_export_environment.sh index a895c7b..090b70e 100644 --- a/ios/Flutter/flutter_export_environment.sh +++ b/ios/Flutter/flutter_export_environment.sh @@ -1,12 +1,12 @@ #!/bin/sh # This is a generated file; do not edit or check into version control. -export "FLUTTER_ROOT=E:\New folder\flutter" -export "FLUTTER_APPLICATION_PATH=C:\Users\USER\Desktop\Flutter-Instagram-UI-Clone" +export "FLUTTER_ROOT=C:\src\flutter\flutter" +export "FLUTTER_APPLICATION_PATH=C:\Users\alenj\Desktop\Flutter-Instagram-UI-Clone" export "FLUTTER_TARGET=lib\main.dart" export "FLUTTER_BUILD_DIR=build" export "SYMROOT=${SOURCE_ROOT}/../build\ios" export "OTHER_LDFLAGS=$(inherited) -framework Flutter" -export "FLUTTER_FRAMEWORK_DIR=E:\New folder\flutter\bin\cache\artifacts\engine\ios" +export "FLUTTER_FRAMEWORK_DIR=C:\src\flutter\flutter\bin\cache\artifacts\engine\ios" export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NUMBER=1" export "DART_OBFUSCATION=false" diff --git a/lib/CameraView.dart b/lib/CameraView.dart new file mode 100644 index 0000000..c53d545 --- /dev/null +++ b/lib/CameraView.dart @@ -0,0 +1,385 @@ +import 'dart:io'; + +import 'package:camera/camera.dart'; +import 'package:flutter/material.dart'; +import 'package:path/path.dart'; +import 'package:path_provider/path_provider.dart'; + +import 'insta_home.dart'; + +class CameraView extends StatefulWidget { + CameraView({Key key, this.controller}) : super(key: key); + + final PageController controller; + final double iconHeight = 30; + final PageController bottomPageController = + PageController(viewportFraction: .2); + @override + _CameraViewState createState() => _CameraViewState(); +} + +class _CameraViewState extends State + with AutomaticKeepAliveClientMixin { + CameraController _controller; + Future _controllerInizializer; + double cameraHorizontalPosition = 0; + int selectedCameraIndex; + List cameras; + bool _isRecording = false; + bool _isRecordingMode = false; + var videoPath; +// final _timerKey = GlobalKey(); + + Future getCamera() async { + final c = await availableCameras(); + return c.first; + } + + @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'); + } + }); + + getCamera().then((camera) { + if (camera == null) return; + setState(() { + _controller = CameraController( + camera, + ResolutionPreset.high, + ); + _controllerInizializer = _controller.initialize(); + _controllerInizializer.whenComplete(() { + setState(() { + // cameraHorizontalPosition = -(MediaQuery.of(context).size.width*_controller.value.aspectRatio)/2; + }); + }); + }); + }); + } + + @override + void dispose() { + // TODO: implement dispose + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + // TODO: implement build + return Scaffold( + extendBody: true, + // bottomNavigationBar: _buildBottomNavigationBar(), + body: Stack( + alignment: Alignment.center, + children: [ + Positioned.fill( + /* trying to preserve aspect ratio */ + left: cameraHorizontalPosition, + right: cameraHorizontalPosition, + child: FutureBuilder( + future: _controllerInizializer, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return CameraPreview(_controller); + } else { + return Center( + child: CircularProgressIndicator(), + ); + } + }, + ), + ), + Positioned.fill( + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + leading: Icon( + Icons.settings, + size: 30, + ), + actions: [ + GestureDetector( + onTap: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => InstaHome()), + ); + }, + child: Padding( + padding: const EdgeInsets.all(10), + child: Icon( + Icons.close, + size: 30, + )), + ), + ], + ), + body: Container( + child: Stack( + alignment: Alignment.center, + children: [ + Positioned( + bottom: 50, + right: 40, + left: 40, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ +// Container( +// height: 10, +// decoration: BoxDecoration( +// border: Border.all( +// color: Colors.white, +// ), +// borderRadius: BorderRadius.all( +// Radius.circular(5), +// ), +// ), +// child: ClipRRect( +// child: Image.network("" +// Utils.image(), +// ), +// borderRadius: BorderRadius.all( +// Radius.circular(5), +// ), +// ), +// ), + Container( + height: 20, + child: Icon( + Icons.flash_on, + color: Colors.white, + size: 30, + ), + ), + Container( + child: Container( + child: GestureDetector( + onLongPress: () async { + print("TEjas"); + + if (!_isRecording) { + setState(() { + _isRecordingMode = true; + }); + await startVideoRecording().then((value) { + setState(() { + videoPath = value; + }); + }); + } + }, + onLongPressEnd: (value) { + if (!(videoPath == null)) if (_isRecording) { + var path = videoPath; + setState(() { + videoPath = null; + _isRecordingMode = false; + }); + stopVideoRecording().then((value) { + print("Stop Recording"); + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => PreviewScreen( + // videoPath: path, + // type: 'Video', + // )), + // ); + }); + } + }, + onTap: () { + _onCapturePressed(context); + }, + ), + decoration: BoxDecoration( + color: _isRecordingMode + ? Colors.redAccent + : Colors.white, + borderRadius: BorderRadius.all( + Radius.circular(30), + ), + ), + ), + height: 80, + width: 80, + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(40), + ), + border: Border.all( + width: 10, + color: _isRecordingMode + ? Colors.red.withOpacity(.4) + : Colors.white.withOpacity(.5), + ), + ), + ), + Container( + // padding: const EdgeInsets.all(10), + height: 30, + child: GestureDetector( + onTap: () { + _onSwitchCamera(); + }, + child: Icon( + Icons.cached, + size: 40, + ), + ), + ), + ], + ), + ), + Positioned( + right: 0, + left: 0, + bottom: 10, + height: 20, + child: PageView.builder( + controller: widget.bottomPageController, + itemBuilder: (context, index) { + return Text( + "Item $index", + textAlign: TextAlign.center, + style: TextStyle(color: Colors.white), + ); + }, + itemCount: 20, + ), + ), + Positioned( + bottom: 5, + width: 10, + height: 10, + child: Icon( + Icons.arrow_drop_up, + color: Colors.white, + ), + ) + ], + ), + ), + ), + ) + ], + ), + ); + } + + 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(() {}); + } + } + + void _onSwitchCamera() { + selectedCameraIndex = + selectedCameraIndex < cameras.length - 1 ? selectedCameraIndex + 1 : 0; + CameraDescription selectedCamera = cameras[selectedCameraIndex]; + _initCameraController(selectedCamera); + } + + void _onCapturePressed(context) async { + try { + final path = + join((await getTemporaryDirectory()).path, '${DateTime.now()}.png'); + await _controller.takePicture(path); + + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => PreviewScreen( + // imgPath: path, + // type: 'Image', + // )), + // ); + } catch (e) { + // _showCameraException(e); + } + } + + Future startVideoRecording() async { + print('startVideoRecording'); + if (!_controller.value.isInitialized) { + return null; + } + setState(() { + _isRecording = true; + }); + // _timerKey.currentState.startTimer(); + + final Directory extDir = await getApplicationDocumentsDirectory(); + final String dirPath = '${extDir.path}/media'; + await Directory(dirPath).create(recursive: true); + final String filePath = '$dirPath/${DateTime.now()}.mp4'; + + if (_controller.value.isRecordingVideo) { + // A recording is already started, do nothing. + return null; + } + + try { + await _controller.startVideoRecording(filePath); + } on CameraException catch (e) { + print(e); + return null; + } + return filePath; + } + + Future stopVideoRecording() async { + if (!_controller.value.isRecordingVideo) { + return null; + } + // _timerKey.currentState.stopTimer(); + setState(() { + _isRecording = false; + }); + + try { + await _controller.stopVideoRecording(); + } on CameraException catch (e) { + print(e); + return null; + } + } + + @override + // TODO: implement wantKeepAlive + bool get wantKeepAlive => true; +} diff --git a/lib/insta_home.dart b/lib/insta_home.dart index db832dd..6d4dec5 100644 --- a/lib/insta_home.dart +++ b/lib/insta_home.dart @@ -1,26 +1,36 @@ import 'package:flutter/material.dart'; +import 'package:flutter_insta_clone/CameraView.dart'; import 'package:flutter_insta_clone/insta_body.dart'; class InstaHome extends StatelessWidget { - final topBar = new AppBar( - backgroundColor: new Color(0xfff8faf8), - centerTitle: true, - elevation: 1.0, - leading: new Icon(Icons.camera_alt), - title: SizedBox( - height: 35.0, child: Image.asset("assets/images/insta_logo.png")), - actions: [ - Padding( - padding: const EdgeInsets.only(right: 12.0), - child: Icon(Icons.send), - ) - ], - ); - + final controller = PageController(initialPage: 1); @override Widget build(BuildContext context) { return new Scaffold( - appBar: topBar, + appBar: AppBar( + backgroundColor: new Color(0xfff8faf8), + centerTitle: true, + elevation: 1.0, + leading: new IconButton( + icon: Icon(Icons.camera_alt), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + CameraView(controller: this.controller)), + ); + }, + ), + title: SizedBox( + height: 35.0, child: Image.asset("assets/images/insta_logo.png")), + actions: [ + Padding( + padding: const EdgeInsets.only(right: 12.0), + child: Icon(Icons.send), + ) + ], + ), body: new InstaBody(), bottomNavigationBar: new Container( color: Colors.white, diff --git a/pubspec.lock b/pubspec.lock index 69e0d32..2b34823 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,42 +7,49 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.2" + version: "2.5.0-nullsafety.1" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety.1" + camera: + dependency: "direct main" + description: + name: camera + url: "https://pub.dartlang.org" + source: hosted + version: "0.5.8+17" characters: dependency: transitive description: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.1.0-nullsafety.3" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.3" + version: "1.2.0-nullsafety.1" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.1.0-nullsafety.1" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.13" + version: "1.15.0-nullsafety.3" cupertino_icons: dependency: "direct main" description: @@ -56,7 +63,21 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0-nullsafety.1" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "5.2.1" flutter: dependency: "direct main" description: flutter @@ -74,27 +95,90 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "8.5.0" + intl: + dependency: transitive + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.16.1" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.8" + version: "0.12.10-nullsafety.1" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0-nullsafety.3" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety.1" + path_provider: + dependency: "direct main" + description: + name: path_provider + url: "https://pub.dartlang.org" + source: hosted + version: "1.6.27" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+2" + path_provider_macos: + dependency: transitive + description: + name: path_provider_macos + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.4+8" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.4+3" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.13" sky_engine: dependency: transitive description: flutter @@ -106,55 +190,70 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety.2" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.5" + version: "1.10.0-nullsafety.1" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety.1" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "1.1.0-nullsafety.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0-nullsafety.1" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.17" + version: "0.2.19-nullsafety.2" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0-nullsafety.3" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0-nullsafety.3" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.4" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.2" sdks: - dart: ">=2.9.0-14.0.dev <3.0.0" + dart: ">=2.10.0-110 <2.11.0" + flutter: ">=1.12.13+hotfix.5 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 6c52e55..82d423b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -9,6 +9,8 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 font_awesome_flutter: + camera: ^0.5.2+1 + path_provider: ^1.1.0 dev_dependencies: flutter_test: