├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── android ├── .gitignore ├── build.gradle ├── gradle.properties ├── settings.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── studyyoun │ │ └── camera │ │ └── flutter_custom_camera_pugin │ │ ├── FlutterCustomCameraPuginPlugin.java │ │ ├── camera │ │ ├── CameraConfigOptions.java │ │ ├── CameraContas.java │ │ ├── CameraOpenActivity.java │ │ └── PhotoAlbumOpenActivity.java │ │ └── cameralibrary │ │ ├── CameraConfig.java │ │ ├── CameraContact.java │ │ ├── CameraXUtils.java │ │ ├── activity │ │ ├── CameraExampCorpActivity.java │ │ ├── CameraExampShowActivity.java │ │ ├── CameraOpacityShowActivity.java │ │ └── CameraXExampOpenActivity.java │ │ ├── callback │ │ ├── CameraCallBack.java │ │ ├── CameraDarkCallBack.java │ │ ├── CameraPhotoGraphCallback.java │ │ └── CameraSaveCallBack.java │ │ ├── presenter │ │ ├── CameraImageSavePresenter.java │ │ ├── CameraImageShowPresenter.java │ │ ├── CameraPhotoPresenter.java │ │ └── CameraXOpenPresenter.java │ │ ├── utils │ │ ├── BeanClassUtils.java │ │ ├── CameraPhotoFromPhotoAlbum.java │ │ ├── JsonUtils.java │ │ └── LightSensorUtil.java │ │ └── view │ │ ├── CameraCropLayout.java │ │ ├── CameraPreview.java │ │ ├── CropDrawable.java │ │ ├── CropFloatView.java │ │ ├── CropLayout.java │ │ └── ZoomImageView.java │ └── res │ ├── drawable │ └── camera_examp_crop_ripple.xml │ ├── layout │ ├── camera_examp_crop_activity_layout.xml │ ├── camera_examp_open_activity_layout.xml │ ├── camera_examp_show_activity_layout.xml │ ├── camera_open_activity_layout.xml │ └── photo_album_activity_layout.xml │ ├── mipmap-xxhdpi │ ├── camera_change_crecord_icon.png │ ├── camera_flash_open_icon.png │ ├── camera_record_finish.png │ ├── camera_record_icon.png │ ├── camera_select_photo_icon.png │ ├── camera_white_back_icon.png │ └── scanline.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── example ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── studyyoun │ │ │ │ │ └── camera │ │ │ │ │ └── flutter_custom_camera_pugin_example │ │ │ │ │ └── MainActivity.java │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ └── settings.gradle ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── Runner │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── 相机-1.png │ │ │ ├── 相机-2.png │ │ │ ├── 相机-3.png │ │ │ ├── 相机-4.png │ │ │ ├── 相机.png │ │ │ ├── 相机@2x-1.png │ │ │ ├── 相机@2x-2.png │ │ │ ├── 相机@2x-3.png │ │ │ ├── 相机@2x-4.png │ │ │ ├── 相机@2x-5.png │ │ │ ├── 相机@2x-6.png │ │ │ ├── 相机@2x-7.png │ │ │ ├── 相机@2x.png │ │ │ ├── 相机@3x-1.png │ │ │ ├── 相机@3x-2.png │ │ │ ├── 相机@3x-3.png │ │ │ └── 相机@3x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── main.m ├── lib │ └── main.dart ├── pubspec.lock ├── pubspec.yaml └── test │ └── widget_test.dart ├── flutter_custom_camera_pugin.iml ├── gradlew ├── gradlew.bat ├── icons ├── camera_change_crecord_icon.png ├── camera_flash_open_icon.png ├── camera_record_finish.png ├── camera_record_icon.png ├── camera_select_photo_icon.png ├── camera_white_back_icon.png └── scanline.png ├── ios ├── .gitignore ├── Classes │ ├── CameraConfigOption.h │ ├── CameraConfigOption.m │ ├── CameraUtils.h │ ├── CameraUtils.m │ ├── FlutterCustomCameraPuginPlugin.h │ ├── FlutterCustomCameraPuginPlugin.m │ ├── alert │ │ ├── CustomeAlertView.h │ │ └── CustomeAlertView.m │ └── camera │ │ ├── CameraShowViewController.h │ │ ├── CameraShowViewController.m │ │ ├── CameraViewController.h │ │ ├── CameraViewController.m │ │ ├── LeePhotoOrAlbumImagePicker.h │ │ ├── LeePhotoOrAlbumImagePicker.m │ │ ├── TestViewController.h │ │ └── TestViewController.m └── flutter_custom_camera_pugin.podspec ├── lib ├── flutter_custom_camera_pugin.dart └── src │ ├── bean │ ├── camera_config_options.dart │ └── camera_result_info.dart │ └── common_camera_function.dart ├── pubspec.lock ├── pubspec.yaml ├── settings.gradle └── test └── flutter_custom_camera_pugin_test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | 7 | build/ 8 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 84c84fb24914e098667649be04614f6ea19d689c 8 | channel: dev 9 | 10 | project_type: plugin 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | # 0.0.5 3 | 4 | iOS 拍照使用资源策略修改 5 | Demo应用图标更换 6 | Android flutter 1.12 版本 拍照异常问题修复 7 | 8 | # 0.0.4 9 | 10 | 兼容 flutter 1.12 版本 11 | 12 | ## 0.0.3 13 | 14 | > 0.0.3 版本支持的功能 15 | > Android iOS双平台的自定义相机 、相册选择功能 16 | > iOS 平台的底部弹框选择(Android 还不支持) 17 | > 18 | 19 | ## 0.0.1 20 | 21 | * TODO: Describe initial release. 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright(c)2020,早起的年轻人 4 | All rights reserved. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | **题记** 4 | —— 执剑天涯,从你的点滴积累开始,所及之处,必精益求精。 5 | 6 | |[**github?**](https://github.com/zhaolongs) |[测试源码在这里](https://github.com/zhaolongs/FlutterCustomCameraPugin/blob/master/example/lib/main.dart) | [百度同步](https://baijiahao.baidu.com/builder/preview/s?id=1676587101499079482) | 7 | |--|--|--| 8 | | [CSDN](https://biglead.blog.csdn.net/)| [网易云课堂教程](https://study.163.com/instructor/1021406098.htm) | [掘金](https://juejin.im/user/712139263459176)| [EDU学院教程](https://edu.csdn.net/lecturer/1555) | 9 | | [知乎](https://www.zhihu.com/people/zhao-long-90-89/posts)| [Flutter系列文章 ](https://blog.csdn.net/zl18603543572/article/details/93532582) |[头条同步](https://www.toutiao.com/i6867301274614759948/) 10 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200909184228606.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3psMTg2MDM1NDM1NzI=,size_16,color_FFFFFF,t_70#pic_center) 11 | 12 | 实际项目开发中,谷歌官方推荐的几个相机插件总是满足不了需要,更令人不舒服的是在华为某些高版本系列的手机中使用系统相机拍照或者是选择照片会让应用闪退。 13 | 14 | 小编也分析了原因,在这些手机拍照的照片过大,在手机相机拍完的那一瞬间,手机系统还没有处理完照片,然后应用就去读取这个照片,导致系统异常崩溃。 15 | 16 | 至本插件编写的 0.0.1 版本时,各相机应用插件都未修复其兼容性,以小编的性格,那就是再造个轮子,于是乎 本插件就诞生了。 17 | 18 | > 0.0.1 版本 只支持 Android (已发布 2020-09-09) 19 | > 0.0.3 版本 同时支持 iOS (已发布 2020-09-12) 20 | > 0.0.5 版本 自定义相机 同时支持 iOS (已发布 2020-09-15) 21 | 22 | > 0.0.5 版本的功能修复 23 | > iOS平台的图片资源策略修改 24 | 25 | *** 26 | 本插件实现的最终目标​: 27 | 28 | * 1、调用原生默认的自定义相机 29 | 30 | * 2、调用原生的系统相机、相册选择图片 31 | 32 | * 3、拍照或者选择照片后 调用 系统裁剪(自定义)功能 33 | 34 | * 4、在 Flutter Widget 中嵌入 自定义相机,允许使用 Widget 开发的页面布局来操作相机 35 | **** 36 | 如下图是默认情况下自定义相机的页面效果: 37 | 38 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200909175911101.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3psMTg2MDM1NDM1NzI=,size_16,color_FFFFFF,t_70#pic_center) 39 | 40 | *** 41 | 42 | #### 1 添加依赖 43 | 小编以将这个自定义相机封装成一个插件组件,直接使用flutter_custom_camera_pugin插件就可使用,一般小编的作风就是提供两种集成方式如下: 44 | 45 | 通过**pub仓库**添加依赖,代码如下:[最新版本查看这里](https://pub.flutter-io.cn/packages/flutter_custom_camera_pugin) 46 | 47 | ```java 48 | dependencies: 49 | flutter_custom_camera_pugin: ^0.0.1 50 | ``` 51 | 52 | 或者是通过 **github** [点击查看github](https://github.com/zhaolongs/FlutterCustomCameraPugin.git)方式添加依赖,代码如下: 53 | 54 | ```java 55 | dependencies: 56 | shake_animation_widget: 57 | git: 58 | url: https://github.com/zhaolongs/FlutterCustomCameraPugin.git 59 | ref: master 60 | ``` 61 | 62 | 然后加载依赖,代码如下: 63 | 64 | ```java 65 | flutter pub get 66 | ``` 67 | 68 | 然后在使用的地方导包,代码如下: 69 | 70 | ```java 71 | import 'package:flutter_custom_camera_pugin/flutter_custom_camera_pugin.dart'; 72 | ``` 73 | 74 | 75 | #### 2 打开自定义相机 拍照 76 | 你可以使用 FlutterCustomCameraPugin 的 openCamera 方法来打开自定义相机拍照页面,其中 可选参数 cameraConfigOptions 用来配置自定义相机页面的的按钮是否显示,如下代码清单 2-1: 77 | ```java 78 | ///代码清单 2-1 79 | ///打开相机 80 | void openCamera() async { 81 | CameraConfigOptions options = new CameraConfigOptions(); 82 | 83 | ///默认自定义相册是否显示 相册切换 84 | options.isShowSelectCamera = true; 85 | 86 | ///默认自定义相册是否显示 前后镜头切换 87 | options.isShowPhotoAlbum = true; 88 | 89 | ///默认自定义相册是否显示 闪光灯开关按钮 90 | options.isShowFlashButtonCamera = true; 91 | 92 | ///调起自定义相机 93 | ///拍照的返回结果 94 | CameraResultInfo resultInfo = 95 | await FlutterCustomCameraPugin.openCamera(cameraConfigOptions: options); 96 | 97 | if (resultInfo.code == 200) { 98 | imageFile = new File(resultInfo.data["lImageUrl"]); 99 | }else if (resultInfo.code == 201) { 100 | ///201 是拍照取消 如点击了关闭按钮 101 | ///或者是 Android 手机的后退按钮 102 | } 103 | setState(() {}); 104 | } 105 | 106 | ``` 107 | 108 | CameraConfigOptions 用来配置相机参数,如下所示: 109 | 110 | ```java 111 | /// 相册配置使用参数 112 | class CameraConfigOptions { 113 | 114 | ///0.0.1 版本 115 | ///默认自定义相册是否显示 相册切换 116 | bool isShowPhotoAlbum = true; 117 | 118 | ///默认自定义相册是否显示 前后镜头切换 119 | bool isShowSelectCamera = true; 120 | 121 | ///默认自定义相册是否显示 闪光灯开关按钮 122 | bool isShowFlashButtonCamera = true; 123 | 124 | } 125 | ``` 126 | CameraResultInfo 是拍照或者相册选择结果封闭,拍照成功、拍照取消、相册选择成功、相册选择失败均会回调: 127 | 128 | ```java 129 | class CameraResultInfo { 130 | ///消息标识 131 | int code; 132 | ///回调的消息 133 | String message =''; 134 | ///回调的数据 135 | dynamic data ; 136 | ///回调的方法名 137 | String method =''; 138 | } 139 | ``` 140 | 141 | #### 3 打开 相册选择照片 142 | 143 | ```java 144 | ///打开相册 145 | void openPhotoAlbum() async { 146 | /// 相册的选择返回结果 147 | /// 选择成功与取消都会回调 148 | CameraResultInfo resultInfo =await FlutterCustomCameraPugin.openPhotoAlbum(); 149 | if (resultInfo.code == 200) { 150 | imageFile = new File(resultInfo.data["lImageUrl"]); 151 | } 152 | } 153 | ``` 154 | 155 | #### 4 打开一个弹框选择 156 | 157 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200912221916959.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3psMTg2MDM1NDM1NzI=,size_16,color_FFFFFF,t_70#pic_center) 158 | 159 | ```java 160 | void openSystemAlert() async { 161 | /// 相册的选择返回结果 162 | /// 选择成功与取消都会回调 163 | CameraResultInfo resultInfo =await FlutterCustomCameraPugin.openSystemAlert(); 164 | 165 | if (resultInfo.code == 200) { 166 | imageFile = new File(resultInfo.data["lImageUrl"]); 167 | } 168 | 169 | setState(() {}); 170 | } 171 | ``` 172 | 173 | 本公众号会首发系列专题文章,付费的视频课程会在公众号中免费刊登,在你上下班的路上或者是睡觉前的一刻,本公众号都是你浏览知识干货的一个小选择,收藏不如行动,在那一刻,公众号会提示你该学习了。 174 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200914205134479.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3psMTg2MDM1NDM1NzI=,size_16,color_FFFFFF,t_70#pic_center) 175 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | group 'com.studyyoun.camera.flutter_custom_camera_pugin' 2 | version '1.0' 3 | 4 | buildscript { 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.5.0' 12 | } 13 | } 14 | 15 | rootProject.allprojects { 16 | repositories { 17 | google() 18 | jcenter() 19 | } 20 | } 21 | 22 | apply plugin: 'com.android.library' 23 | 24 | android { 25 | compileSdkVersion 28 26 | 27 | defaultConfig { 28 | minSdkVersion 16 29 | } 30 | lintOptions { 31 | disable 'InvalidPackage' 32 | } 33 | 34 | dependencies { 35 | implementation fileTree(include: ['*.aar'], dir: 'libs') 36 | // implementation(name: 'cameralibrary-release', ext: 'aar') 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'flutter_custom_camera_pugin' -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 16 | 20 | 23 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/camera/CameraConfigOptions.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.camera; 2 | 3 | /* 4 | * 创建人: Created by on 2020/9/9. 5 | * 创建时间:Created by on 2020/9/9. 6 | * 页面说明: 7 | * 可关注公众号:我的大前端生涯 获取最新技术分享 8 | * 可关注网易云课堂:https://study.163.com/instructor/1021406098.htm 9 | * 可关注博客:https://blog.csdn.net/zl18603543572 10 | */ 11 | 12 | import java.io.Serializable; 13 | 14 | public class CameraConfigOptions implements Serializable { 15 | 16 | ///默认自定义相册是否显示 相册切换 17 | public boolean isShowPhotoAlbum = true; 18 | 19 | ///默认自定义相册是否显示 前后镜头切换 20 | public boolean isShowSelectCamera = true; 21 | 22 | ///默认自定义相册是否显示 闪光灯开关按钮 23 | public boolean isShowFlashButtonCamera = true; 24 | 25 | /// 是否预览照片 如拍照完成 或者相册选择完成 26 | public boolean isPreviewImage = true; 27 | 28 | /// 是否启动裁剪功能 如拍照完成 或者相册选择完成 29 | public boolean isCropImage = false; 30 | /// 是否显示提示 31 | public boolean isShowToast = true ; 32 | 33 | public boolean isShowPhotoAlbum() { 34 | return isShowPhotoAlbum; 35 | } 36 | 37 | public void setShowPhotoAlbum(boolean showPhotoAlbum) { 38 | isShowPhotoAlbum = showPhotoAlbum; 39 | } 40 | 41 | public boolean isShowSelectCamera() { 42 | return isShowSelectCamera; 43 | } 44 | 45 | public void setShowSelectCamera(boolean showSelectCamera) { 46 | isShowSelectCamera = showSelectCamera; 47 | } 48 | 49 | public boolean isShowFlashButtonCamera() { 50 | return isShowFlashButtonCamera; 51 | } 52 | 53 | public void setShowFlashButtonCamera(boolean showFlashButtonCamera) { 54 | isShowFlashButtonCamera = showFlashButtonCamera; 55 | } 56 | 57 | public boolean isPreviewImage() { 58 | return isPreviewImage; 59 | } 60 | 61 | public void setPreviewImage(boolean previewImage) { 62 | isPreviewImage = previewImage; 63 | } 64 | 65 | public boolean isCropImage() { 66 | return isCropImage; 67 | } 68 | 69 | public void setCropImage(boolean cropImage) { 70 | isCropImage = cropImage; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/camera/CameraContas.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.camera; 2 | 3 | /* 4 | * 创建人: Created by on 2020/9/9. 5 | * 创建时间:Created by on 2020/9/9. 6 | * 页面说明: 7 | * 可关注公众号:我的大前端生涯 获取最新技术分享 8 | * 可关注网易云课堂:https://study.163.com/instructor/1021406098.htm 9 | * 可关注博客:https://blog.csdn.net/zl18603543572 10 | */ 11 | 12 | public class CameraContas { 13 | public static final String actionFinishCamera="cameraactivityfinish"; 14 | } 15 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/camera/PhotoAlbumOpenActivity.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.camera; 2 | 3 | import android.app.Activity; 4 | import android.content.BroadcastReceiver; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.IntentFilter; 8 | import android.net.Uri; 9 | import android.os.Bundle; 10 | import android.util.DisplayMetrics; 11 | import android.util.Log; 12 | import android.view.View; 13 | import android.view.Window; 14 | import android.view.WindowManager; 15 | import android.widget.FrameLayout; 16 | import android.widget.LinearLayout; 17 | 18 | import com.studyyoun.camera.flutter_custom_camera_pugin.R; 19 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.CameraXUtils; 20 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.activity.CameraExampShowActivity; 21 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.callback.CameraCallBack; 22 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.callback.CameraPhotoGraphCallback; 23 | 24 | import static com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.CameraConfig.LOGTAG; 25 | 26 | 27 | /** 28 | * 打开相册 29 | */ 30 | public class PhotoAlbumOpenActivity extends Activity { 31 | 32 | private CameraXUtils mCameraUtils; 33 | 34 | private Uri mImageUri; 35 | private String mMImagePath; 36 | private String mKey; 37 | private String mFilePath; 38 | private Context mContext; 39 | private DisplayMetrics mDisplayMetrics; 40 | private FinishActivityRecivier mFinishActivityRecivier; 41 | private int mCropWidth; 42 | private int mCropHeight; 43 | private boolean mMICrop; 44 | private CameraConfigOptions mCameraConfigOptions ; 45 | 46 | @Override 47 | protected void onCreate(Bundle savedInstanceState) { 48 | super.onCreate(savedInstanceState); 49 | requestNoTitle(); 50 | setContentView(getCommonLayoutId()); 51 | mContext = this; 52 | mDisplayMetrics = mContext.getResources().getDisplayMetrics(); 53 | 54 | Intent lIntent = getIntent(); 55 | mCropWidth = lIntent.getIntExtra("cropWidth",500); 56 | mCropHeight = lIntent.getIntExtra("cropHeight",500); 57 | 58 | mMICrop = lIntent.getBooleanExtra("mICrop",false); 59 | 60 | mCameraConfigOptions = (CameraConfigOptions) getIntent().getSerializableExtra("cameraConfigOptions"); 61 | 62 | 63 | mCameraUtils = CameraXUtils.getInstance(); 64 | CameraXUtils.getInstance().openCapTureGroupFunction(PhotoAlbumOpenActivity.this); 65 | 66 | 67 | mFinishActivityRecivier = new FinishActivityRecivier(); 68 | registerReceiver(mFinishActivityRecivier, new IntentFilter("cameraactivityfinish")); 69 | } 70 | 71 | protected void requestNoTitle() { 72 | //去除标题栏 73 | requestWindowFeature(Window.FEATURE_NO_TITLE); 74 | //去除状态栏 75 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 76 | WindowManager.LayoutParams.FLAG_FULLSCREEN); 77 | 78 | } 79 | 80 | protected int getCommonLayoutId() { 81 | return R.layout.photo_album_activity_layout; 82 | } 83 | 84 | 85 | 86 | @Override 87 | protected void onStart() { 88 | super.onStart(); 89 | 90 | } 91 | 92 | @Override 93 | protected void onDestroy() { 94 | super.onDestroy(); 95 | mCameraUtils.destore(); 96 | unregisterReceiver(mFinishActivityRecivier); 97 | } 98 | 99 | 100 | private CameraPhotoGraphCallback mCameraPhotoGraphCallback = new CameraPhotoGraphCallback() { 101 | @Override 102 | public void onSuccess(String s) { 103 | Log.d(LOGTAG, "相册路径处理 " + s); 104 | showImageFunction(s); 105 | } 106 | 107 | @Override 108 | public void onFaile(String s) { 109 | //异常 110 | Log.e(LOGTAG, "相册选取图片失败" + s); 111 | Intent lIntent = new Intent("cameraactivityfinish"); 112 | lIntent.putExtra("code",101); 113 | PhotoAlbumOpenActivity.this.sendBroadcast(lIntent); 114 | } 115 | }; 116 | 117 | private void showImageFunction(String mFilePath) { 118 | this.mFilePath = mFilePath; 119 | //加载显示图片 120 | final Intent lIntent = new Intent(PhotoAlbumOpenActivity.this, CameraExampShowActivity.class); 121 | lIntent.putExtra("imageUrl", mFilePath); 122 | lIntent.putExtra("mCropHeight", mCropHeight); 123 | lIntent.putExtra("mCropWidth", mCropWidth); 124 | lIntent.putExtra("mICrop", mMICrop); 125 | lIntent.putExtra("cameraConfigOptions",mCameraConfigOptions); 126 | Log.d(LOGTAG, "imageUrl " + mFilePath); 127 | 128 | ///发一个广播 129 | Intent intentRecivier=new Intent(); 130 | intentRecivier.setAction("cameraRecivierAction"); 131 | intentRecivier.putExtra("imageUrl", mFilePath); 132 | intentRecivier.putExtra("mCropHeight", mCropHeight); 133 | intentRecivier.putExtra("mCropWidth", mCropWidth); 134 | intentRecivier.putExtra("mICrop", mMICrop); 135 | PhotoAlbumOpenActivity.this.sendBroadcast(intentRecivier); 136 | 137 | PhotoAlbumOpenActivity.this.startActivity(lIntent); 138 | } 139 | 140 | @Override 141 | public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 142 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 143 | //权限回调 144 | mCameraUtils.onRequestPermissionsResult(requestCode, permissions, grantResults); 145 | } 146 | 147 | @Override 148 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 149 | super.onActivityResult(requestCode, resultCode, data); 150 | if (resultCode == RESULT_OK) { 151 | mCameraUtils.onActivityResult(requestCode, resultCode, data, mContext, mCameraPhotoGraphCallback); 152 | }else { 153 | //发送取消操作广播 154 | Intent lIntent = new Intent(CameraContas.actionFinishCamera); 155 | lIntent.putExtra("code",101); 156 | PhotoAlbumOpenActivity.this.sendBroadcast(lIntent); 157 | finish(); 158 | } 159 | } 160 | 161 | class FinishActivityRecivier extends BroadcastReceiver{ 162 | 163 | @Override 164 | public void onReceive(Context context, Intent intent) { 165 | PhotoAlbumOpenActivity.this.finish(); 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/CameraConfig.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary; 2 | 3 | public class CameraConfig { 4 | public static final String LOGTAG ="carmer"; 5 | } 6 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/CameraContact.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | 6 | import androidx.annotation.Nullable; 7 | 8 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.callback.CameraPhotoGraphCallback; 9 | 10 | public interface CameraContact { 11 | 12 | /** 13 | * 工具类功能 14 | * 1 自定义相机 15 | * 2 打开相册 16 | */ 17 | interface CommonCameraInterface { 18 | //开始录制 19 | void start(); 20 | 21 | //停止录制 22 | void stop(); 23 | 24 | //权限请求回调 25 | void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults); 26 | 27 | //销毁 28 | void destore(); 29 | 30 | //切换摄像头 31 | void changeCameraClick(); 32 | 33 | CameraXUtils setXContinuous(boolean continuous); 34 | 35 | //重新拍照 36 | void reCameraClick(); 37 | 38 | //拍照 39 | void onCameraClick(); 40 | 41 | //打开相册 42 | void openCapTureGroupFunction(Context context); 43 | 44 | //相册选图回调 45 | void onActivityResult(int requestCode, int resultCode, @Nullable Intent data, Context context, CameraPhotoGraphCallback callback); 46 | 47 | void openCameraFlashFunction(); 48 | } 49 | 50 | interface CameraPresenter { 51 | void stop(); 52 | void start(); 53 | void reCameraClick(); 54 | void onCameraClick(); 55 | void openCameraFlashFunction(); 56 | void destore(); 57 | } 58 | 59 | //打开相册 60 | interface PhotoPresenter { 61 | //打开相册 62 | void openCapTureGroupFunction(Context context); 63 | 64 | //相册选图回调 65 | void onActivityResult(int requestCode, int resultCode, Intent data, Context context, CameraPhotoGraphCallback callback); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/CameraXUtils.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.widget.FrameLayout; 6 | 7 | import androidx.annotation.Nullable; 8 | 9 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.callback.CameraCallBack; 10 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.callback.CameraDarkCallBack; 11 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.callback.CameraPhotoGraphCallback; 12 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.presenter.CameraPhotoPresenter; 13 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.presenter.CameraXOpenPresenter; 14 | 15 | 16 | public class CameraXUtils implements CameraContact.CommonCameraInterface { 17 | 18 | 19 | private static CameraXUtils mCameraUtils; 20 | private final CameraXOpenPresenter mCameraOpenPresenter; 21 | private final CameraPhotoPresenter mCameraPhotoPresenter; 22 | 23 | private CameraXUtils() { 24 | mCameraOpenPresenter = new CameraXOpenPresenter(); 25 | mCameraPhotoPresenter = new CameraPhotoPresenter(); 26 | } 27 | public static CameraXUtils getInstance() { 28 | if (mCameraUtils == null) { 29 | mCameraUtils = new CameraXUtils(); 30 | } 31 | return mCameraUtils; 32 | } 33 | public CameraXUtils initCamerView(Context context, FrameLayout frameLayout, int picWidth, int picHeight, CameraCallBack callBack) { 34 | mCameraOpenPresenter.init(context,frameLayout,picWidth,picHeight,callBack); 35 | return mCameraUtils; 36 | } 37 | 38 | @Override 39 | public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 40 | } 41 | @Override 42 | public void destore() { 43 | mCameraOpenPresenter.destore(); 44 | } 45 | 46 | @Override 47 | public void changeCameraClick() { 48 | mCameraOpenPresenter.changeCameraClick(); 49 | } 50 | 51 | 52 | 53 | @Override 54 | public CameraXUtils setXContinuous(boolean continuous) { 55 | mCameraOpenPresenter.setContinuous(continuous); 56 | return mCameraUtils; 57 | } 58 | @Override 59 | public void reCameraClick() { 60 | mCameraOpenPresenter.reCameraClick(); 61 | } 62 | @Override 63 | public void start(){ 64 | mCameraOpenPresenter.start(); 65 | } 66 | @Override 67 | public void stop(){ 68 | mCameraOpenPresenter.stop(); 69 | } 70 | 71 | @Override 72 | public void onCameraClick() { 73 | mCameraOpenPresenter.onCameraClick(); 74 | } 75 | @Override 76 | public void openCapTureGroupFunction(Context context) { 77 | mCameraPhotoPresenter.openCapTureGroupFunction(context); 78 | } 79 | @Override 80 | public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data, Context context, CameraPhotoGraphCallback callback) { 81 | mCameraPhotoPresenter.onActivityResult(requestCode,resultCode,data,context,callback); 82 | } 83 | @Override 84 | public void openCameraFlashFunction() { 85 | mCameraOpenPresenter.openCameraFlashFunction(); 86 | } 87 | 88 | 89 | public void setLineDarkCallBack(CameraDarkCallBack pLineDarkCallBack){ 90 | mCameraOpenPresenter.setCameraDarkCallBack(pLineDarkCallBack); 91 | } 92 | public void setIsUseShopPreview(boolean flag){ 93 | mCameraOpenPresenter.setShotPreview(flag); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/activity/CameraExampCorpActivity.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.activity; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.view.Window; 8 | import android.view.WindowManager; 9 | import android.widget.Toast; 10 | 11 | import com.studyyoun.camera.flutter_custom_camera_pugin.R; 12 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.callback.CameraSaveCallBack; 13 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.presenter.CameraImageSavePresenter; 14 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.presenter.CameraImageShowPresenter; 15 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.view.CropLayout; 16 | 17 | 18 | public class CameraExampCorpActivity extends Activity { 19 | private String mUrl; 20 | private CropLayout mCropLayout; 21 | private int mCropHeight; 22 | private int mCropWidth; 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | //去除标题栏 28 | requestWindowFeature(Window.FEATURE_NO_TITLE); 29 | //去除状态栏 30 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 31 | WindowManager.LayoutParams.FLAG_FULLSCREEN); 32 | mUrl = getIntent().getStringExtra("imageUrl"); 33 | mCropHeight =getIntent().getIntExtra("mCropHeight",500); 34 | mCropWidth =getIntent().getIntExtra("mCropWidth", 500); 35 | setContentView(R.layout.camera_examp_crop_activity_layout); 36 | mCropLayout = findViewById(R.id.cropLayout); 37 | mCropLayout.setCropHeight(mCropHeight); 38 | mCropLayout.setCropWidth(mCropWidth); 39 | commonDelayFunction(); 40 | } 41 | 42 | 43 | protected void commonDelayFunction() { 44 | findViewById(R.id.tv_crop).setOnClickListener(new View.OnClickListener() { 45 | @Override 46 | public void onClick(View v) { 47 | 48 | //保存裁剪内容 49 | saveCropImageFunction(); 50 | } 51 | }); 52 | findViewById(R.id.tv_cancel).setOnClickListener(new View.OnClickListener() { 53 | @Override 54 | public void onClick(View v) { 55 | finish(); 56 | } 57 | }); 58 | 59 | CameraImageShowPresenter.getInstance().showImage(mCropLayout.getImageView(),mUrl); 60 | 61 | mCropLayout.start(); 62 | } 63 | 64 | private void saveCropImageFunction() { 65 | CameraImageSavePresenter.getInstance().saveImage(this, mCropLayout.cropBitmap(), new CameraSaveCallBack() { 66 | @Override 67 | public void cameraFaile(int errCode, String message) { 68 | Toast.makeText(CameraExampCorpActivity.this,"保存异常 ",Toast.LENGTH_LONG).show(); 69 | } 70 | 71 | @Override 72 | public void cameraSuccess(String mFilePath) { 73 | Toast.makeText(CameraExampCorpActivity.this,"已保存 "+mFilePath,Toast.LENGTH_LONG).show(); 74 | Intent lIntent = new Intent("cameraactivityfinish"); 75 | lIntent.putExtra("filePath",mFilePath); 76 | lIntent.putExtra("code",100); 77 | CameraExampCorpActivity.this.sendBroadcast(lIntent); 78 | CameraExampCorpActivity.this.finish(); 79 | } 80 | 81 | @Override 82 | public void cameraPermisExit() { 83 | 84 | } 85 | }); 86 | 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/activity/CameraExampShowActivity.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.activity; 2 | 3 | import android.app.Activity; 4 | import android.content.BroadcastReceiver; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.IntentFilter; 8 | import android.os.Bundle; 9 | import android.os.Handler; 10 | import android.os.Looper; 11 | import android.view.KeyEvent; 12 | import android.view.View; 13 | import android.view.Window; 14 | import android.view.WindowManager; 15 | import android.widget.FrameLayout; 16 | import android.widget.ImageView; 17 | import android.widget.LinearLayout; 18 | import android.widget.TextView; 19 | import android.widget.Toast; 20 | 21 | import com.studyyoun.camera.flutter_custom_camera_pugin.R; 22 | import com.studyyoun.camera.flutter_custom_camera_pugin.camera.CameraConfigOptions; 23 | import com.studyyoun.camera.flutter_custom_camera_pugin.camera.CameraContas; 24 | import com.studyyoun.camera.flutter_custom_camera_pugin.camera.CameraOpenActivity; 25 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.presenter.CameraImageShowPresenter; 26 | 27 | 28 | /** 29 | * 用来预览图片的 30 | */ 31 | 32 | public class CameraExampShowActivity extends Activity { 33 | 34 | private FinishActivityRecivier mFinishActivityRecivier; 35 | private int mCropWidth; 36 | private int mCropHeight; 37 | private boolean mIsCorpBoolean; 38 | private long preClickTime = 0; 39 | private ImageView mShowImageView; 40 | private String mImageUrl; 41 | private boolean mImageLoading = false; 42 | private LinearLayout mLoadingLayout; 43 | private String mSource; 44 | 45 | private CameraConfigOptions mCameraConfigOptions ; 46 | private LinearLayout mNextLayout; 47 | private LinearLayout mBackLayout; 48 | private TextView mShowLoadingText; 49 | private FrameLayout mRootLayout; 50 | 51 | @Override 52 | protected void onCreate(Bundle savedInstanceState) { 53 | super.onCreate(savedInstanceState); 54 | requestNoTitle(); 55 | setContentView(R.layout.camera_examp_show_activity_layout); 56 | 57 | 58 | mLoadingLayout = findViewById(R.id.ll_image_loading_view); 59 | mShowImageView = findViewById(R.id.iv_photo_select); 60 | mImageUrl = getIntent().getStringExtra("imageUrl"); 61 | 62 | mCropHeight = getIntent().getIntExtra("mCropHeight", 500); 63 | mCropWidth = getIntent().getIntExtra("mCropWidth", 500); 64 | mIsCorpBoolean = getIntent().getBooleanExtra("mICrop", false); 65 | 66 | mSource = getIntent().getStringExtra("source"); 67 | 68 | mCameraConfigOptions = (CameraConfigOptions) getIntent().getSerializableExtra("cameraConfigOptions"); 69 | 70 | ininViewFunction(); 71 | new Handler(Looper.myLooper()).postDelayed(new Runnable() { 72 | @Override 73 | public void run() { 74 | loadingImage(); 75 | } 76 | }, 1000); 77 | 78 | 79 | mBackLayout.setOnClickListener(new View.OnClickListener() { 80 | @Override 81 | public void onClick(View v) { 82 | 83 | int code = 101 ; 84 | if(mSource!=null&&mSource.equals("camera")){ 85 | code = 102 ; 86 | } 87 | //发送取消操作广播 88 | Intent lIntent = new Intent(CameraContas.actionFinishCamera); 89 | lIntent.putExtra("code", code); 90 | CameraExampShowActivity.this.sendBroadcast(lIntent); 91 | 92 | 93 | CameraExampShowActivity.this.finish(); 94 | } 95 | }); 96 | 97 | mNextLayout.setOnClickListener(new View.OnClickListener() { 98 | @Override 99 | public void onClick(View v) { 100 | long currentTime = System.currentTimeMillis(); 101 | long flagTime = currentTime - preClickTime; 102 | if (flagTime < 2000 || !mImageLoading) { 103 | Toast.makeText(CameraExampShowActivity.this, "图片正在加载中", Toast.LENGTH_SHORT).show(); 104 | } else { 105 | if (mIsCorpBoolean) { 106 | final Intent lIntent = new Intent(CameraExampShowActivity.this, CameraExampCorpActivity.class); 107 | lIntent.putExtra("imageUrl", mImageUrl); 108 | lIntent.putExtra("mCropHeight", mCropHeight); 109 | lIntent.putExtra("mCropWidth", mCropWidth); 110 | CameraExampShowActivity.this.startActivity(lIntent); 111 | } else { 112 | 113 | nextSaveFunction(); 114 | } 115 | } 116 | 117 | 118 | } 119 | }); 120 | 121 | mFinishActivityRecivier = new FinishActivityRecivier(); 122 | registerReceiver(mFinishActivityRecivier, new IntentFilter("cameraactivityfinish")); 123 | 124 | 125 | 126 | 127 | } 128 | 129 | private void nextSaveFunction() { 130 | if (mCameraConfigOptions.isShowToast) { 131 | Toast.makeText(CameraExampShowActivity.this, "已保存 " + mImageUrl, Toast.LENGTH_LONG).show(); 132 | } 133 | 134 | Intent lIntent = new Intent("cameraactivityfinish"); 135 | lIntent.putExtra("filePath", mImageUrl); 136 | lIntent.putExtra("code", 100); 137 | CameraExampShowActivity.this.sendBroadcast(lIntent); 138 | CameraExampShowActivity.this.finish(); 139 | } 140 | 141 | private void ininViewFunction() { 142 | 143 | mNextLayout = findViewById(R.id.ll_base_next); 144 | mBackLayout = findViewById(R.id.ll_base_back); 145 | 146 | mShowLoadingText = findViewById(R.id.tv_show_loading); 147 | 148 | mRootLayout = findViewById(R.id.fr_root_view); 149 | 150 | ///配置是否显示操作按钮 151 | 152 | if (mCameraConfigOptions.isPreviewImage) { 153 | 154 | mNextLayout.setVisibility(View.VISIBLE); 155 | mBackLayout.setVisibility(View.VISIBLE); 156 | mShowImageView.setVisibility(View.VISIBLE); 157 | mShowLoadingText.setText("加载中 ..."); 158 | mRootLayout.setBackgroundColor(getResources().getColor(R.color.black)); 159 | }else{ 160 | 161 | mNextLayout.setVisibility(View.GONE); 162 | mBackLayout.setVisibility(View.GONE); 163 | mShowImageView.setVisibility(View.GONE); 164 | mShowLoadingText.setText("处理中 ..."); 165 | mRootLayout.setBackgroundColor(getResources().getColor(R.color.trans)); 166 | } 167 | 168 | } 169 | 170 | private void loadingImage() { 171 | CameraImageShowPresenter.getInstance().showImage(mShowImageView, mImageUrl, new CameraImageShowPresenter.OnCamerImageShowCallBack() { 172 | @Override 173 | public void onFinish(int flag, String message) { 174 | mImageLoading = true; 175 | mLoadingLayout.setVisibility(View.GONE); 176 | 177 | if (!mCameraConfigOptions.isPreviewImage && mCameraConfigOptions.isCropImage) { 178 | /// 不预览直接 到裁剪页面 179 | 180 | }else if(!mCameraConfigOptions.isPreviewImage){ 181 | ///不预览直接关闭 182 | nextSaveFunction(); 183 | } 184 | } 185 | }); 186 | } 187 | 188 | private void requestNoTitle() { 189 | //去除标题栏 190 | requestWindowFeature(Window.FEATURE_NO_TITLE); 191 | //去除状态栏 192 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 193 | WindowManager.LayoutParams.FLAG_FULLSCREEN); 194 | 195 | 196 | 197 | 198 | } 199 | 200 | @Override 201 | protected void onDestroy() { 202 | super.onDestroy(); 203 | unregisterReceiver(mFinishActivityRecivier); 204 | } 205 | 206 | @Override 207 | public boolean onKeyUp(int keyCode, KeyEvent event) { 208 | if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { 209 | int code = 101 ; 210 | if(mSource!=null&&mSource.equals("camera")){ 211 | code = 102 ; 212 | } 213 | //发送取消操作广播 214 | Intent lIntent = new Intent(CameraContas.actionFinishCamera); 215 | lIntent.putExtra("code", code); 216 | CameraExampShowActivity.this.sendBroadcast(lIntent); 217 | finish(); 218 | //不执行父类点击事件 219 | return true; 220 | } 221 | //继续执行父类其他点击事件 222 | return super.onKeyUp(keyCode, event); 223 | } 224 | 225 | 226 | class FinishActivityRecivier extends BroadcastReceiver { 227 | 228 | @Override 229 | public void onReceive(Context context, Intent intent) { 230 | CameraExampShowActivity.this.finish(); 231 | } 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/activity/CameraOpacityShowActivity.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.activity; 2 | 3 | import android.app.Activity; 4 | import android.content.BroadcastReceiver; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.IntentFilter; 8 | import android.os.Bundle; 9 | import android.os.Handler; 10 | import android.os.Looper; 11 | import android.view.KeyEvent; 12 | import android.view.View; 13 | import android.view.Window; 14 | import android.view.WindowManager; 15 | import android.widget.ImageView; 16 | import android.widget.LinearLayout; 17 | import android.widget.Toast; 18 | 19 | import com.studyyoun.camera.flutter_custom_camera_pugin.R; 20 | import com.studyyoun.camera.flutter_custom_camera_pugin.camera.CameraContas; 21 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.presenter.CameraImageShowPresenter; 22 | 23 | 24 | /** 25 | * 不是用来 预览图片的 26 | * 是拍照完成后 27 | */ 28 | 29 | public class CameraOpacityShowActivity extends Activity { 30 | 31 | private FinishActivityRecivier mFinishActivityRecivier; 32 | private int mCropWidth; 33 | private int mCropHeight; 34 | private boolean mIsCorpBoolean; 35 | private long preClickTime = 0; 36 | private ImageView mShowImageView; 37 | private String mImageUrl; 38 | private boolean mImageLoading = false; 39 | private LinearLayout mLoadingLayout; 40 | private String mSource; 41 | 42 | @Override 43 | protected void onCreate(Bundle savedInstanceState) { 44 | super.onCreate(savedInstanceState); 45 | requestNoTitle(); 46 | setContentView(R.layout.camera_examp_show_activity_layout); 47 | 48 | 49 | mLoadingLayout = findViewById(R.id.ll_image_loading_view); 50 | mShowImageView = findViewById(R.id.iv_photo_select); 51 | mImageUrl = getIntent().getStringExtra("imageUrl"); 52 | 53 | mCropHeight = getIntent().getIntExtra("mCropHeight", 500); 54 | mCropWidth = getIntent().getIntExtra("mCropWidth", 500); 55 | mIsCorpBoolean = getIntent().getBooleanExtra("mICrop", false); 56 | 57 | mSource = getIntent().getStringExtra("source"); 58 | 59 | new Handler(Looper.myLooper()).postDelayed(new Runnable() { 60 | @Override 61 | public void run() { 62 | loadingImage(); 63 | } 64 | }, 1000); 65 | 66 | 67 | findViewById(R.id.ll_base_back).setOnClickListener(new View.OnClickListener() { 68 | @Override 69 | public void onClick(View v) { 70 | 71 | int code = 101 ; 72 | if(mSource!=null&&mSource.equals("camera")){ 73 | code = 102 ; 74 | } 75 | //发送取消操作广播 76 | Intent lIntent = new Intent(CameraContas.actionFinishCamera); 77 | lIntent.putExtra("code", code); 78 | CameraOpacityShowActivity.this.sendBroadcast(lIntent); 79 | 80 | 81 | CameraOpacityShowActivity.this.finish(); 82 | } 83 | }); 84 | 85 | findViewById(R.id.ll_base_next).setOnClickListener(new View.OnClickListener() { 86 | @Override 87 | public void onClick(View v) { 88 | long currentTime = System.currentTimeMillis(); 89 | long flagTime = currentTime - preClickTime; 90 | if (flagTime < 2000 || !mImageLoading) { 91 | Toast.makeText(CameraOpacityShowActivity.this, "图片正在加载中", Toast.LENGTH_SHORT).show(); 92 | } else { 93 | if (mIsCorpBoolean) { 94 | final Intent lIntent = new Intent(CameraOpacityShowActivity.this, CameraExampCorpActivity.class); 95 | lIntent.putExtra("imageUrl", mImageUrl); 96 | lIntent.putExtra("mCropHeight", mCropHeight); 97 | lIntent.putExtra("mCropWidth", mCropWidth); 98 | CameraOpacityShowActivity.this.startActivity(lIntent); 99 | } else { 100 | 101 | Toast.makeText(CameraOpacityShowActivity.this, "已保存 " + mImageUrl, Toast.LENGTH_LONG).show(); 102 | Intent lIntent = new Intent("cameraactivityfinish"); 103 | lIntent.putExtra("filePath", mImageUrl); 104 | lIntent.putExtra("code", 100); 105 | CameraOpacityShowActivity.this.sendBroadcast(lIntent); 106 | CameraOpacityShowActivity.this.finish(); 107 | } 108 | } 109 | 110 | 111 | } 112 | }); 113 | 114 | mFinishActivityRecivier = new FinishActivityRecivier(); 115 | registerReceiver(mFinishActivityRecivier, new IntentFilter("cameraactivityfinish")); 116 | 117 | 118 | } 119 | 120 | private void loadingImage() { 121 | CameraImageShowPresenter.getInstance().showImage(mShowImageView, mImageUrl, new CameraImageShowPresenter.OnCamerImageShowCallBack() { 122 | @Override 123 | public void onFinish(int flag, String message) { 124 | mImageLoading = true; 125 | mLoadingLayout.setVisibility(View.GONE); 126 | } 127 | }); 128 | } 129 | 130 | private void requestNoTitle() { 131 | //去除标题栏 132 | requestWindowFeature(Window.FEATURE_NO_TITLE); 133 | //去除状态栏 134 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 135 | WindowManager.LayoutParams.FLAG_FULLSCREEN); 136 | 137 | } 138 | 139 | @Override 140 | protected void onDestroy() { 141 | super.onDestroy(); 142 | unregisterReceiver(mFinishActivityRecivier); 143 | } 144 | 145 | @Override 146 | public boolean onKeyUp(int keyCode, KeyEvent event) { 147 | if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { 148 | int code = 101 ; 149 | if(mSource!=null&&mSource.equals("camera")){ 150 | code = 102 ; 151 | } 152 | //发送取消操作广播 153 | Intent lIntent = new Intent(CameraContas.actionFinishCamera); 154 | lIntent.putExtra("code", code); 155 | CameraOpacityShowActivity.this.sendBroadcast(lIntent); 156 | finish(); 157 | //不执行父类点击事件 158 | return true; 159 | } 160 | //继续执行父类其他点击事件 161 | return super.onKeyUp(keyCode, event); 162 | } 163 | 164 | 165 | class FinishActivityRecivier extends BroadcastReceiver { 166 | 167 | @Override 168 | public void onReceive(Context context, Intent intent) { 169 | CameraOpacityShowActivity.this.finish(); 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/callback/CameraCallBack.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.callback; 2 | 3 | public interface CameraCallBack { 4 | void cameraFaile(int errCode, String message); 5 | void cameraSuccess(String mFilePath); 6 | void cameraPermisExit(); 7 | } 8 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/callback/CameraDarkCallBack.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.callback; 2 | 3 | import android.hardware.SensorEvent; 4 | 5 | /** 6 | * Create by alv1 on 2019/6/13 7 | */ 8 | public interface CameraDarkCallBack { 9 | void onLineDark(long pCameraLight); 10 | 11 | void onLineNoDark(long pCameraLight); 12 | 13 | void onDarkList(long[] pDarkList, long pCameraLight); 14 | 15 | void onSensorChanged(SensorEvent pEvent, float pLux); 16 | } 17 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/callback/CameraPhotoGraphCallback.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.callback; 2 | 3 | public interface CameraPhotoGraphCallback { 4 | public void onSuccess(String photh); 5 | void onFaile(String message); 6 | } 7 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/callback/CameraSaveCallBack.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.callback; 2 | 3 | public interface CameraSaveCallBack { 4 | void cameraFaile(int errCode, String message); 5 | void cameraSuccess(String mFilePath); 6 | void cameraPermisExit(); 7 | } 8 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/presenter/CameraImageSavePresenter.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.presenter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.os.AsyncTask; 6 | import android.os.Environment; 7 | 8 | 9 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.callback.CameraSaveCallBack; 10 | 11 | import java.io.File; 12 | import java.io.FileOutputStream; 13 | 14 | public class CameraImageSavePresenter { 15 | 16 | private Context mContext; 17 | private static CameraImageSavePresenter mCameraImageShowPresenter; 18 | public static final String IMAGE_TYPE = ".jpeg"; 19 | private CameraSaveCallBack mCameraSaveCallBack; 20 | private CameraImageSavePresenter(){ 21 | 22 | } 23 | public static CameraImageSavePresenter getInstance(){ 24 | if (mCameraImageShowPresenter==null) { 25 | mCameraImageShowPresenter=new CameraImageSavePresenter(); 26 | } 27 | return mCameraImageShowPresenter; 28 | } 29 | public static String getPhotoFileName() { 30 | return Environment.getExternalStorageDirectory().getPath() + File.separator + System.currentTimeMillis() + IMAGE_TYPE; 31 | } 32 | 33 | public void saveImage(Context context,Bitmap bitmap,CameraSaveCallBack callBack){ 34 | this.mContext =context; 35 | this.mCameraSaveCallBack=callBack; 36 | CameraImageShowAsyncTask lCameraImageShowAsyncTask = new CameraImageShowAsyncTask( mContext, this.mCameraSaveCallBack); 37 | lCameraImageShowAsyncTask.execute(bitmap); 38 | } 39 | 40 | 41 | static class CameraImageShowAsyncTask extends AsyncTask { 42 | 43 | private CameraSaveCallBack mCameraSaveCallBack; 44 | CameraImageShowAsyncTask( Context context,CameraSaveCallBack callBack) { 45 | mCameraSaveCallBack = callBack; 46 | } 47 | 48 | @Override 49 | protected String doInBackground(Bitmap... bitmaps) { 50 | FileOutputStream outStream = null; 51 | String fileName = getPhotoFileName(); 52 | Bitmap lBitmap = bitmaps[0]; 53 | try { 54 | outStream = new FileOutputStream(fileName); 55 | // 把数据写入文件,100表示不压缩 56 | lBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream); 57 | return fileName; 58 | } catch (Exception e) { 59 | e.printStackTrace(); 60 | return null; 61 | } finally { 62 | try { 63 | if (outStream != null) { 64 | // 记得要关闭流! 65 | outStream.close(); 66 | } 67 | if (lBitmap != null) { 68 | lBitmap.recycle(); 69 | } 70 | } catch (Exception e) { 71 | e.printStackTrace(); 72 | } 73 | } 74 | 75 | } 76 | 77 | @Override 78 | protected void onPostExecute(String path) { 79 | super.onPostExecute(path); 80 | if (mCameraSaveCallBack != null) { 81 | if (path==null){ 82 | mCameraSaveCallBack.cameraFaile(-2,"异常 "); 83 | }else { 84 | mCameraSaveCallBack.cameraSuccess(path); 85 | } 86 | } 87 | 88 | } 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/presenter/CameraImageShowPresenter.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.presenter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.Matrix; 7 | import android.os.AsyncTask; 8 | import android.text.TextUtils; 9 | import android.util.Log; 10 | import android.widget.ImageView; 11 | 12 | import java.io.File; 13 | import java.lang.ref.WeakReference; 14 | 15 | public class CameraImageShowPresenter { 16 | 17 | public interface OnCamerImageShowCallBack{ 18 | void onFinish(int flag, String message); 19 | } 20 | 21 | 22 | private OnCamerImageShowCallBack mOnCamerImageShowCallBack; 23 | private ImageView mImageView; 24 | private Context mContext; 25 | private static CameraImageShowPresenter mCameraImageShowPresenter; 26 | private CameraImageShowPresenter(){ 27 | 28 | } 29 | public static CameraImageShowPresenter getInstance(){ 30 | if (mCameraImageShowPresenter==null) { 31 | mCameraImageShowPresenter=new CameraImageShowPresenter(); 32 | } 33 | return mCameraImageShowPresenter; 34 | } 35 | 36 | public void showImage(ImageView imageView,String locationImagePath){ 37 | showImage(imageView,locationImagePath,null); 38 | } 39 | public void showImage(ImageView imageView,String locationImagePath,OnCamerImageShowCallBack imageShowCallBack){ 40 | this.mImageView = imageView; 41 | this.mContext = imageView.getContext(); 42 | this.mOnCamerImageShowCallBack = imageShowCallBack; 43 | CameraImageShowAsyncTask lCameraImageShowAsyncTask = new CameraImageShowAsyncTask(this, mContext, imageView,imageShowCallBack); 44 | lCameraImageShowAsyncTask.execute(locationImagePath); 45 | } 46 | 47 | static class CameraImageShowAsyncTask extends AsyncTask { 48 | 49 | private WeakReference ref; 50 | private float maxWidth; 51 | private float maxHeight; 52 | private OnCamerImageShowCallBack mOnCamerImageShowCallBack; 53 | 54 | CameraImageShowAsyncTask(CameraImageShowPresenter activity, Context context, ImageView imageView, OnCamerImageShowCallBack imageShowCallBack) { 55 | ref = new WeakReference<>(activity); 56 | maxWidth = imageView.getMeasuredWidth(); 57 | maxHeight =imageView.getMeasuredHeight(); 58 | mOnCamerImageShowCallBack = imageShowCallBack; 59 | } 60 | 61 | @Override 62 | protected Bitmap doInBackground(String... thumbnailPaths) { 63 | Bitmap bmp = null; 64 | try { 65 | if (ref != null) { 66 | CameraImageShowPresenter publishActivity = ref.get(); 67 | if (publishActivity != null) { 68 | String path = thumbnailPaths[0]; 69 | if (TextUtils.isEmpty(path)) { 70 | return null; 71 | } 72 | File thumbnail = new File(path); 73 | if (!thumbnail.exists()) { 74 | return null; 75 | } 76 | BitmapFactory.Options opt = new BitmapFactory.Options(); 77 | opt.inJustDecodeBounds = true; 78 | BitmapFactory.decodeFile(path, opt); 79 | float bw = opt.outWidth; 80 | float bh = opt.outHeight; 81 | float scale; 82 | if (bw > bh) { 83 | scale = bw / maxWidth; 84 | } else { 85 | scale = bh / maxHeight; 86 | } 87 | boolean needScaleAfterDecode = scale != 1; 88 | opt.inJustDecodeBounds = false; 89 | bmp = BitmapFactory.decodeFile(path, opt); 90 | if (needScaleAfterDecode) { 91 | bmp = publishActivity.scaleBitmap(bmp, scale); 92 | } 93 | } 94 | } 95 | } catch (Exception e) { 96 | Log.e("errMessage" ,""+ e.getMessage()); 97 | } 98 | 99 | return bmp; 100 | } 101 | 102 | @Override 103 | protected void onPostExecute(Bitmap bitmap) { 104 | super.onPostExecute(bitmap); 105 | if (bitmap != null && ref != null && ref.get() != null) { 106 | ref.get().initThumbnail(bitmap); 107 | } 108 | if (mOnCamerImageShowCallBack != null) { 109 | mOnCamerImageShowCallBack.onFinish(0,"success"); 110 | } 111 | } 112 | } 113 | 114 | private void initThumbnail(Bitmap thumbnail) { 115 | if (thumbnail != null&&mImageView!=null) { 116 | mImageView.setImageBitmap(thumbnail); 117 | }else { 118 | 119 | } 120 | } 121 | 122 | private Bitmap scaleBitmap(Bitmap bmp, float scale) { 123 | Matrix mi = new Matrix(); 124 | mi.setScale(1 / scale, 1 / scale); 125 | Bitmap temp = bmp; 126 | bmp = Bitmap.createBitmap(temp, 0, 0, temp.getWidth(), temp.getHeight(), mi, false); 127 | temp.recycle(); 128 | return bmp; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/presenter/CameraPhotoPresenter.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.presenter; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.net.Uri; 7 | import android.os.Environment; 8 | import android.provider.MediaStore; 9 | 10 | 11 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.CameraContact; 12 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.callback.CameraPhotoGraphCallback; 13 | import com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.utils.CameraPhotoFromPhotoAlbum; 14 | 15 | import java.io.File; 16 | import java.io.IOException; 17 | 18 | import static android.app.Activity.RESULT_OK; 19 | 20 | public class CameraPhotoPresenter implements CameraContact.PhotoPresenter { 21 | //相册 22 | private Uri mImageUri; 23 | private String mMImagePath; 24 | 25 | @Override 26 | public void openCapTureGroupFunction(Context context) { 27 | //同样new一个file用于存放照片 28 | File imageFile = new File(Environment 29 | .getExternalStorageDirectory(), "outputImage.jpg"); 30 | if (imageFile.exists()) { 31 | imageFile.delete(); 32 | } 33 | try { 34 | imageFile.createNewFile(); 35 | } catch (IOException e) { 36 | // TODO Auto-generated catch block 37 | } 38 | //转换成Uri 39 | mImageUri = Uri.fromFile(imageFile); 40 | mMImagePath = imageFile.getPath(); 41 | //开启选择呢绒界面 42 | Intent intent = new Intent("android.intent.action.GET_CONTENT"); 43 | //设置可以缩放 44 | intent.putExtra("scale", true); 45 | //设置可以裁剪 46 | intent.putExtra("crop", false); 47 | intent.setType("image/*"); 48 | //设置输出位置 49 | intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri); 50 | //开始选择 51 | ((Activity) context).startActivityForResult(intent, 12); 52 | } 53 | @Override 54 | public void onActivityResult(int requestCode, int resultCode, Intent data, Context context, CameraPhotoGraphCallback callback) { 55 | 56 | if (resultCode == RESULT_OK) { 57 | if (requestCode == 12) { 58 | try { 59 | String photh = CameraPhotoFromPhotoAlbum.getRealPathFromUri(context, data.getData()); 60 | if (callback != null) { 61 | callback.onSuccess(photh); 62 | } 63 | } catch (Exception e) { 64 | e.printStackTrace(); 65 | if (callback != null) { 66 | callback.onFaile(e.getMessage()); 67 | } 68 | } 69 | 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/utils/BeanClassUtils.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.utils; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.InvocationTargetException; 5 | import java.lang.reflect.Method; 6 | import java.util.Map; 7 | /* 8 | * 创建人: Created by on 2020/9/9. 9 | * 创建时间:Created by on 2020/9/9. 10 | * 页面说明: 11 | * 可关注公众号:我的大前端生涯 获取最新技术分享 12 | * 可关注网易云课堂:https://study.163.com/instructor/1021406098.htm 13 | * 可关注博客:https://blog.csdn.net/zl18603543572 14 | */ 15 | 16 | 17 | /** 18 | * 工具类将map转成对应对象的方法,入参是map和目标实体类,我们的实体类中是标准的set、get方法, 19 | * 要map转成对应的实体类对象需要map中的字段和我们实体类的属性字段匹配。获取到map中的字段,然后拼装成标准的set方法, 20 | * 利用反射获取到我们目标实体类对象中的这个set方法,并把相应的参数放进去调用。 21 | * 22 | * 可能存在的问题:1、需要map中字段和实体类对象的字段匹配,并且实体类中get\set方法要标准; 23 | * 2、利用反射效率会比较低。 24 | */ 25 | 26 | import java.lang.reflect.InvocationTargetException; 27 | import java.util.Map; 28 | 29 | @SuppressWarnings("all") 30 | public class BeanClassUtils { 31 | 32 | /** 33 | * 用于将map转成对象 34 | * 35 | * @param map 36 | * @param object 37 | * @return 38 | * @throws Exception 39 | */ 40 | public static T mapToObject(Map map, T object) { 41 | 42 | Field[] fields = object.getClass().getDeclaredFields(); 43 | for (int i = 0; i < fields.length; i++) { 44 | String fieldName = fields[i].getName(); 45 | String key = toUpperCaseFirstOne(fieldName); 46 | String mapValue = (map.get(key) == null ? "" : map.get(key).toString()); 47 | try { 48 | object.getClass().getMethod("set" + key, String.class).invoke(object, mapValue); 49 | } catch (IllegalAccessException e) { 50 | e.printStackTrace(); 51 | } catch (IllegalArgumentException e) { 52 | e.printStackTrace(); 53 | } catch (InvocationTargetException e) { 54 | e.printStackTrace(); 55 | } catch (NoSuchMethodException e) { 56 | e.printStackTrace(); 57 | } catch (Exception e) { 58 | e.printStackTrace(); 59 | } 60 | } 61 | return object; 62 | } 63 | 64 | 65 | //首字母转小写 66 | public static String toLowerCaseFirstOne(String s) { 67 | if (Character.isLowerCase(s.charAt(0))) 68 | return s; 69 | else 70 | return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString(); 71 | } 72 | 73 | 74 | //首字母转大写 75 | public static String toUpperCaseFirstOne(String s) { 76 | if (Character.isUpperCase(s.charAt(0))) 77 | return s; 78 | else 79 | return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString(); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/utils/CameraPhotoFromPhotoAlbum.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.utils; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.ContentUris; 5 | import android.content.Context; 6 | import android.database.Cursor; 7 | import android.net.Uri; 8 | import android.os.Build; 9 | import android.provider.DocumentsContract; 10 | import android.provider.MediaStore; 11 | 12 | public class CameraPhotoFromPhotoAlbum { 13 | /** 14 | * 根据Uri获取图片的绝对路径 15 | * 16 | * @param context 上下文对象 17 | * @param uri 图片的Uri 18 | * @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null 19 | */ 20 | public static String getRealPathFromUri(Context context, Uri uri) { 21 | int sdkVersion = Build.VERSION.SDK_INT; 22 | if (sdkVersion >= 19) { 23 | return getRealPathFromUriAboveApi19(context, uri); 24 | } else { 25 | return getRealPathFromUriBelowAPI19(context, uri); 26 | } 27 | } 28 | 29 | /** 30 | * 适配api19以下(不包括api19),根据uri获取图片的绝对路径 31 | * 32 | * @param context 上下文对象 33 | * @param uri 图片的Uri 34 | * @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null 35 | */ 36 | private static String getRealPathFromUriBelowAPI19(Context context, Uri uri) { 37 | return getDataColumn(context, uri, null, null); 38 | } 39 | 40 | /** 41 | * 适配api19及以上,根据uri获取图片的绝对路径 42 | * 43 | * @param context 上下文对象 44 | * @param uri 图片的Uri 45 | * @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null 46 | */ 47 | @SuppressLint("NewApi") 48 | private static String getRealPathFromUriAboveApi19(Context context, Uri uri) { 49 | String filePath = null; 50 | if (DocumentsContract.isDocumentUri(context, uri)) { 51 | // 如果是document类型的 uri, 则通过document id来进行处理 52 | String documentId = DocumentsContract.getDocumentId(uri); 53 | if (isMediaDocument(uri)) { 54 | // 使用':'分割 55 | String id = documentId.split(":")[1]; 56 | 57 | String selection = MediaStore.Images.Media._ID + "=?"; 58 | String[] selectionArgs = {id}; 59 | filePath = getDataColumn(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection, selectionArgs); 60 | } else if (isDownloadsDocument(uri)) { 61 | Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(documentId)); 62 | filePath = getDataColumn(context, contentUri, null, null); 63 | } 64 | } else if ("content".equalsIgnoreCase(uri.getScheme())) { 65 | // 如果是 content 类型的 Uri 66 | filePath = getDataColumn(context, uri, null, null); 67 | } else if ("file".equals(uri.getScheme())) { 68 | // 如果是 file 类型的 Uri,直接获取图片对应的路径 69 | filePath = uri.getPath(); 70 | } 71 | return filePath; 72 | } 73 | 74 | /** 75 | * 获取数据库表中的 _data 列,即返回Uri对应的文件路径 76 | */ 77 | private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { 78 | String path = null; 79 | 80 | String[] projection = new String[]{MediaStore.Images.Media.DATA}; 81 | Cursor cursor = null; 82 | try { 83 | cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); 84 | if (cursor != null && cursor.moveToFirst()) { 85 | int columnIndex = cursor.getColumnIndexOrThrow(projection[0]); 86 | path = cursor.getString(columnIndex); 87 | } 88 | } catch (Exception e) { 89 | if (cursor != null) { 90 | cursor.close(); 91 | } 92 | } 93 | return path; 94 | } 95 | 96 | /** 97 | * @param uri the Uri to check 98 | * @return Whether the Uri authority is MediaProvider 99 | */ 100 | private static boolean isMediaDocument(Uri uri) { 101 | return "com.android.providers.media.documents".equals(uri.getAuthority()); 102 | } 103 | 104 | /** 105 | * @param uri the Uri to check 106 | * @return Whether the Uri authority is DownloadsProvider 107 | */ 108 | private static boolean isDownloadsDocument(Uri uri) { 109 | return "com.android.providers.downloads.documents".equals(uri.getAuthority()); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/utils/JsonUtils.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.utils; 2 | 3 | /* 4 | * 创建人: Created by on 2020/9/9. 5 | * 创建时间:Created by on 2020/9/9. 6 | * 页面说明: 7 | * 可关注公众号:我的大前端生涯 获取最新技术分享 8 | * 可关注网易云课堂:https://study.163.com/instructor/1021406098.htm 9 | * 可关注博客:https://blog.csdn.net/zl18603543572 10 | */ 11 | 12 | import android.util.Log; 13 | 14 | import org.json.JSONArray; 15 | import org.json.JSONException; 16 | import org.json.JSONObject; 17 | 18 | import java.util.HashMap; 19 | import java.util.Iterator; 20 | import java.util.Map; 21 | 22 | public class JsonUtils { 23 | private static final JsonUtils ourInstance = new JsonUtils(); 24 | 25 | static JsonUtils getInstance() { 26 | return ourInstance; 27 | } 28 | 29 | private JsonUtils() { 30 | } 31 | 32 | 33 | /** 34 | * @param content json字符串 35 | * @return 如果转换失败返回null, 36 | */ 37 | Map jsonToMap(String content) { 38 | content = content.trim(); 39 | Map result = new HashMap<>(); 40 | try { 41 | if (content.charAt(0) == '[') { 42 | JSONArray jsonArray = new JSONArray(content); 43 | for (int i = 0; i < jsonArray.length(); i++) { 44 | Object value = jsonArray.get(i); 45 | if (value instanceof JSONArray || value instanceof JSONObject) { 46 | result.put(i + "", jsonToMap(value.toString().trim())); 47 | } else { 48 | result.put(i + "", jsonArray.getString(i)); 49 | } 50 | } 51 | } else if (content.charAt(0) == '{') { 52 | JSONObject jsonObject = new JSONObject(content); 53 | Iterator iterator = jsonObject.keys(); 54 | while (iterator.hasNext()) { 55 | String key = iterator.next(); 56 | Object value = jsonObject.get(key); 57 | if (value instanceof JSONArray || value instanceof JSONObject) { 58 | result.put(key, jsonToMap(value.toString().trim())); 59 | } else { 60 | result.put(key, value.toString().trim()); 61 | } 62 | } 63 | } else { 64 | Log.e("异常", "json2Map: 字符串格式错误"); 65 | } 66 | } catch (JSONException e) { 67 | Log.e("异常", "json2Map: ", e); 68 | result = null; 69 | } 70 | return result; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/utils/LightSensorUtil.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.utils; 2 | 3 | import android.content.Context; 4 | import android.hardware.Sensor; 5 | import android.hardware.SensorEventListener; 6 | import android.hardware.SensorManager; 7 | 8 | /** 9 | * Create by alv1 on 2019/6/13 10 | */ 11 | public class LightSensorUtil { 12 | 13 | private LightSensorUtil() { 14 | } 15 | 16 | public static SensorManager getSenosrManager(Context context){ 17 | return (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); 18 | } 19 | 20 | /** 21 | * 注册光线传感器监听器 22 | * @param sensorManager 23 | * @param listener 24 | */ 25 | public static void registerLightSensor(SensorManager sensorManager,SensorEventListener listener) { 26 | if(sensorManager == null || listener == null){ 27 | return; 28 | } 29 | Sensor lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); // 获取光线传感器 30 | if (lightSensor != null) { // 光线传感器存在时 31 | sensorManager.registerListener(listener, lightSensor, SensorManager.SENSOR_DELAY_NORMAL); // 注册事件监听 32 | } 33 | } 34 | /** 35 | * 反注册光线传感器监听器 36 | * @param sensorManager 37 | * @param listener 38 | */ 39 | public static void unregisterLightSensor(SensorManager sensorManager, SensorEventListener listener) { 40 | if(sensorManager == null || listener == null){ 41 | return; 42 | } 43 | sensorManager.unregisterListener(listener); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/view/CameraCropLayout.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.view; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.util.AttributeSet; 6 | import android.view.Display; 7 | import android.view.ViewGroup; 8 | import android.view.WindowManager; 9 | import android.widget.FrameLayout; 10 | 11 | public class CameraCropLayout extends FrameLayout { 12 | private int mCropWidth = 500;//设置裁剪宽度 13 | private int mCropHeight = 500;//设置裁剪高度 14 | 15 | private ZoomImageView mZoomImageView; 16 | private CropFloatView mCropView; 17 | 18 | public CameraCropLayout(Context context, AttributeSet attrs) { 19 | super(context, attrs); 20 | mZoomImageView = new ZoomImageView(context); 21 | mCropView = new CropFloatView(context); 22 | ViewGroup.LayoutParams lp = new LayoutParams( 23 | ViewGroup.LayoutParams.MATCH_PARENT, 24 | ViewGroup.LayoutParams.MATCH_PARENT); 25 | this.addView(mZoomImageView, lp); 26 | this.addView(mCropView, lp); 27 | } 28 | 29 | public ZoomImageView getImageView() { 30 | return mZoomImageView; 31 | } 32 | 33 | 34 | public Bitmap cropBitmap() { 35 | return mZoomImageView.cropBitmap(); 36 | } 37 | 38 | public void setCropWidth(int mCropWidth) { 39 | this.mCropWidth = mCropWidth; 40 | mCropView.setCropWidth(mCropWidth); 41 | mZoomImageView.setCropWidth(mCropWidth); 42 | } 43 | 44 | public void setCropHeight(int mCropHeight) { 45 | this.mCropHeight = mCropHeight; 46 | mCropView.setCropHeight(mCropHeight); 47 | mZoomImageView.setCropHeight(mCropHeight); 48 | } 49 | 50 | public void start() { 51 | int height = getScreenHeight(getContext()); 52 | int width = getScreenWidth(getContext()); 53 | int mHOffset = (width - mCropWidth) / 2; 54 | int mVOffset = (height - mCropHeight) / 2; 55 | mZoomImageView.setHOffset(mHOffset); 56 | mZoomImageView.setVOffset(mVOffset); 57 | mCropView.setHOffset(mHOffset); 58 | mCropView.setVOffset(mVOffset); 59 | } 60 | 61 | /** 62 | * 获得屏幕的宽度 63 | * 64 | * @param context context 65 | * @return width 66 | */ 67 | public static int getScreenWidth(Context context) { 68 | WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 69 | Display display = manager.getDefaultDisplay(); 70 | return display.getWidth(); 71 | } 72 | 73 | /** 74 | * 获得屏幕的高度 75 | * 76 | * @param context context 77 | * @return height 78 | */ 79 | public static int getScreenHeight(Context context) { 80 | WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 81 | Display display = manager.getDefaultDisplay(); 82 | return display.getHeight(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/view/CameraPreview.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.view; 2 | 3 | import android.content.Context; 4 | import android.hardware.Camera; 5 | import android.view.SurfaceHolder; 6 | import android.view.SurfaceView; 7 | 8 | import java.io.IOException; 9 | 10 | public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 11 | private SurfaceHolder mHolder; 12 | private Camera mCamera; 13 | 14 | public CameraPreview(Context context, Camera camera) { 15 | super(context); 16 | //初始化Camera对象 17 | mCamera = camera; 18 | //得到SurfaceHolder对象 19 | mHolder = getHolder(); 20 | //添加回调,得到Surface的三个声明周期方法 21 | mHolder.addCallback(this); 22 | // deprecated setting, but required on Android versions prior to 3.0 23 | mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 24 | } 25 | 26 | @Override 27 | public void surfaceCreated(SurfaceHolder holder) { 28 | try { 29 | //设置预览方向 30 | mCamera.setDisplayOrientation(90); 31 | //把这个预览效果展示在SurfaceView上面 32 | mCamera.setPreviewDisplay(holder); 33 | //开启预览效果 34 | mCamera.startPreview(); 35 | } catch (IOException e) { 36 | // Log.d(TAG, "Error setting camera preview: " + e.getMessage()); 37 | } 38 | 39 | } 40 | 41 | @Override 42 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 43 | if (holder.getSurface() == null) { 44 | return; 45 | } 46 | //停止预览效果 47 | mCamera.stopPreview(); 48 | //重新设置预览效果 49 | try { 50 | mCamera.setPreviewDisplay(mHolder); 51 | } catch (IOException e) { 52 | e.printStackTrace(); 53 | } 54 | mCamera.startPreview(); 55 | } 56 | 57 | @Override 58 | public void surfaceDestroyed(SurfaceHolder holder) { 59 | 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/view/CropDrawable.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.view; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.ColorFilter; 7 | import android.graphics.Paint; 8 | import android.graphics.PixelFormat; 9 | import android.graphics.Rect; 10 | import android.graphics.drawable.Drawable; 11 | import android.view.Display; 12 | import android.view.WindowManager; 13 | 14 | /** 15 | * Created by haibin 16 | * on 2016/12/1. 17 | */ 18 | @SuppressWarnings("ALL") 19 | public class CropDrawable extends Drawable { 20 | private Context mContext; 21 | private int offset = 50; 22 | 23 | private Paint mCornerPaint = new Paint(); 24 | private Paint mLinePaint = new Paint(); 25 | private Paint mNineLinePaint = new Paint(); 26 | 27 | private int mCropWidth = 800, mCropHeight = 800; 28 | 29 | private static final int RADIUS = 20; 30 | 31 | public int mLeft, mRight, mTop, mBottom; 32 | 33 | public CropDrawable(Context mContext) { 34 | this.mContext = mContext; 35 | initPaint(); 36 | } 37 | 38 | private void initPaint() { 39 | mLinePaint.setColor(Color.WHITE); 40 | mLinePaint.setAntiAlias(true); 41 | mLinePaint.setStrokeWidth(2); 42 | mLinePaint.setStyle(Paint.Style.STROKE); 43 | 44 | mNineLinePaint.setColor(Color.WHITE); 45 | mNineLinePaint.setAntiAlias(true); 46 | mNineLinePaint.setStrokeWidth(1); 47 | mNineLinePaint.setStyle(Paint.Style.STROKE); 48 | 49 | mCornerPaint.setColor(Color.WHITE); 50 | mCornerPaint.setAntiAlias(true); 51 | mCornerPaint.setStrokeWidth(8); 52 | mCornerPaint.setStyle(Paint.Style.FILL); 53 | } 54 | /** 55 | * 获得屏幕的宽度 56 | * 57 | * @param context context 58 | * @return width 59 | */ 60 | public static int getScreenWidth(Context context) { 61 | WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 62 | Display display = manager.getDefaultDisplay(); 63 | return display.getWidth(); 64 | } 65 | 66 | /** 67 | * 获得屏幕的高度 68 | * 69 | * @param context context 70 | * @return height 71 | */ 72 | public static int getScreenHeight(Context context) { 73 | WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 74 | Display display = manager.getDefaultDisplay(); 75 | return display.getHeight(); 76 | } 77 | @Override 78 | public void draw(Canvas canvas) { 79 | int width = getScreenWidth(mContext); 80 | int height =getScreenHeight(mContext); 81 | mLeft = (width - mCropWidth) / 2; 82 | mTop = (height - mCropHeight) / 2; 83 | mRight = (width + mCropWidth) / 2; 84 | mBottom = (height + mCropHeight) / 2; 85 | Rect rect = new Rect(mLeft, mTop, mRight, mBottom); 86 | canvas.drawRect(rect, mLinePaint); 87 | //左上 88 | canvas.drawLine(mLeft, mTop, mLeft, mTop + 50, mCornerPaint); 89 | canvas.drawLine(mLeft - 4, mTop, mLeft + 50, mTop, mCornerPaint); 90 | 91 | //右上 92 | canvas.drawLine(mRight, mTop, mRight, mTop + 50, mCornerPaint); 93 | canvas.drawLine(mRight - 50, mTop, mRight + 4, mTop, mCornerPaint); 94 | 95 | //左下 96 | canvas.drawLine(mLeft, mBottom, mLeft + 50, mBottom, mCornerPaint); 97 | canvas.drawLine(mLeft, mBottom - 50, mLeft, mBottom + 4, mCornerPaint); 98 | 99 | //右下 100 | canvas.drawLine(mRight, mBottom, mRight, mBottom - 50, mCornerPaint); 101 | canvas.drawLine(mRight - 50, mBottom, mRight + 4, mBottom, mCornerPaint); 102 | 103 | int index = canvas.save(); 104 | canvas.clipRect(rect); 105 | //画九宫格 106 | int vAvg = mCropWidth / 3; 107 | int hAvg = mCropHeight / 3; 108 | canvas.drawLine(mLeft + vAvg, mTop, mLeft + vAvg, mBottom, mNineLinePaint); 109 | canvas.drawLine(mLeft + vAvg * 2, mTop, mLeft + vAvg * 2, mBottom, mNineLinePaint); 110 | 111 | canvas.drawLine(mLeft, mTop + hAvg, mRight, mTop + hAvg, mNineLinePaint); 112 | canvas.drawLine(mLeft, mTop + hAvg * 2, mRight, mTop + hAvg * 2, mNineLinePaint); 113 | 114 | canvas.restoreToCount(index); 115 | } 116 | 117 | @Override 118 | public void setAlpha(int alpha) { 119 | 120 | } 121 | 122 | public void offset(int x, int y) { 123 | getBounds().offset(x, y); 124 | } 125 | 126 | @Override 127 | public void setBounds(Rect bounds) { 128 | super.setBounds(new Rect(mLeft, mTop, mRight, mBottom)); 129 | } 130 | 131 | @Override 132 | public void setColorFilter(ColorFilter colorFilter) { 133 | 134 | } 135 | 136 | @Override 137 | public int getOpacity() { 138 | return PixelFormat.UNKNOWN; 139 | } 140 | 141 | public void setRegion(Rect rect) { 142 | int width = getScreenWidth(mContext); 143 | int height = getScreenHeight(mContext); 144 | rect.set((width - mCropWidth) / 2, (height - mCropHeight) / 2, (width + mCropWidth) / 2, (height + mCropHeight) / 2); 145 | } 146 | 147 | public int getLeft() { 148 | return mLeft; 149 | } 150 | 151 | 152 | public int getRight() { 153 | return mRight; 154 | } 155 | 156 | 157 | public int getTop() { 158 | return mCropHeight; 159 | } 160 | 161 | 162 | public int getBottom() { 163 | return mBottom; 164 | } 165 | 166 | public void setCropWidth(int mCropWidth) { 167 | this.mCropWidth = mCropWidth; 168 | } 169 | 170 | public void setCropHeight(int mCropHeight) { 171 | this.mCropHeight = mCropHeight; 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/view/CropFloatView.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.view; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Rect; 7 | import android.graphics.Region; 8 | import android.view.View; 9 | 10 | /** 11 | * Created by haibin 12 | * on 2016/12/2. 13 | */ 14 | 15 | public class CropFloatView extends View { 16 | private int mCropWidth;//设置裁剪宽度 17 | private int mCropHeight;//设置裁剪高度 18 | 19 | private int mHOffset;//水平偏移量 20 | private int mVOffset;//垂直偏移量 21 | 22 | private CropDrawable mCropDrawable; 23 | private Rect mFloatRect = new Rect(); 24 | private boolean isCrop; 25 | 26 | public CropFloatView(Context context) { 27 | super(context); 28 | mCropDrawable = new CropDrawable(context); 29 | } 30 | 31 | @Override 32 | protected void onDraw(Canvas canvas) { 33 | super.onDraw(canvas); 34 | cropDrawable(); 35 | canvas.save(); 36 | canvas.clipRect(mFloatRect, Region.Op.DIFFERENCE); 37 | canvas.drawColor(Color.parseColor("#a0000000")); 38 | canvas.restore(); 39 | mCropDrawable.draw(canvas); 40 | } 41 | 42 | public CropDrawable getCropDrawable() { 43 | return mCropDrawable; 44 | } 45 | 46 | private void cropDrawable() { 47 | if (isCrop) return; 48 | mCropDrawable.setRegion(mFloatRect); 49 | isCrop = true; 50 | } 51 | 52 | public void setCropWidth(int mCropWidth) { 53 | this.mCropWidth = mCropWidth; 54 | mCropDrawable.setCropWidth(mCropWidth); 55 | } 56 | 57 | public void setCropHeight(int mCropHeight) { 58 | this.mCropHeight = mCropHeight; 59 | mCropDrawable.setCropHeight(mCropHeight); 60 | } 61 | 62 | public void setHOffset(int mHOffset) { 63 | this.mHOffset = mHOffset; 64 | } 65 | 66 | public void setVOffset(int mVOffset) { 67 | this.mVOffset = mVOffset; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /android/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin/cameralibrary/view/CropLayout.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin.cameralibrary.view; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.util.AttributeSet; 6 | import android.view.Display; 7 | import android.view.ViewGroup; 8 | import android.view.WindowManager; 9 | import android.widget.FrameLayout; 10 | 11 | public class CropLayout extends FrameLayout { 12 | private int mCropWidth = 500;//设置裁剪宽度 13 | private int mCropHeight = 500;//设置裁剪高度 14 | 15 | private ZoomImageView mZoomImageView; 16 | private CropFloatView mCropView; 17 | 18 | public CropLayout(Context context, AttributeSet attrs) { 19 | super(context, attrs); 20 | mZoomImageView = new ZoomImageView(context); 21 | mCropView = new CropFloatView(context); 22 | ViewGroup.LayoutParams lp = new LayoutParams( 23 | ViewGroup.LayoutParams.MATCH_PARENT, 24 | ViewGroup.LayoutParams.MATCH_PARENT); 25 | this.addView(mZoomImageView, lp); 26 | this.addView(mCropView, lp); 27 | } 28 | 29 | public ZoomImageView getImageView() { 30 | return mZoomImageView; 31 | } 32 | 33 | 34 | public Bitmap cropBitmap() { 35 | return mZoomImageView.cropBitmap(); 36 | } 37 | 38 | public void setCropWidth(int mCropWidth) { 39 | this.mCropWidth = mCropWidth; 40 | mCropView.setCropWidth(mCropWidth); 41 | mZoomImageView.setCropWidth(mCropWidth); 42 | } 43 | 44 | public void setCropHeight(int mCropHeight) { 45 | this.mCropHeight = mCropHeight; 46 | mCropView.setCropHeight(mCropHeight); 47 | mZoomImageView.setCropHeight(mCropHeight); 48 | } 49 | 50 | public void start() { 51 | int height = getScreenHeight(getContext()); 52 | int width = getScreenWidth(getContext()); 53 | int mHOffset = (width - mCropWidth) / 2; 54 | int mVOffset = (height - mCropHeight) / 2; 55 | mZoomImageView.setHOffset(mHOffset); 56 | mZoomImageView.setVOffset(mVOffset); 57 | mCropView.setHOffset(mHOffset); 58 | mCropView.setVOffset(mVOffset); 59 | } 60 | 61 | /** 62 | * 获得屏幕的宽度 63 | * 64 | * @param context context 65 | * @return width 66 | */ 67 | public static int getScreenWidth(Context context) { 68 | WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 69 | Display display = manager.getDefaultDisplay(); 70 | return display.getWidth(); 71 | } 72 | 73 | /** 74 | * 获得屏幕的高度 75 | * 76 | * @param context context 77 | * @return height 78 | */ 79 | public static int getScreenHeight(Context context) { 80 | WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 81 | Display display = manager.getDefaultDisplay(); 82 | return display.getHeight(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /android/src/main/res/drawable/camera_examp_crop_ripple.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/src/main/res/layout/camera_examp_crop_activity_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 22 | 23 | 35 | 36 | 42 | 43 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /android/src/main/res/layout/camera_examp_open_activity_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | 24 | 25 | 30 | 31 | 36 | 37 | 45 | 46 | 47 | 54 | 55 | 63 | 64 | 65 | 73 | 74 | 78 | 79 | 80 | 81 | 89 | 90 | 99 | 100 | 101 | 102 | 103 | 112 | 113 | 118 | 119 | 120 | 121 | 130 | 131 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /android/src/main/res/layout/camera_examp_show_activity_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | 24 | 25 | 30 | 31 | 36 | 37 | 45 | 46 | 47 | 51 | 52 | 58 | 59 | 66 | 67 | 68 | 69 | 75 | 76 | 79 | 80 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /android/src/main/res/layout/camera_open_activity_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | 24 | 25 | 30 | 31 | 36 | 37 | 45 | 46 | 47 | 51 | 52 | 60 | 61 | 70 | 71 | 72 | 80 | 81 | 85 | 86 | 87 | 88 | 96 | 97 | 106 | 107 | 108 | 109 | 110 | 119 | 120 | 126 | 127 | 135 | 136 | 137 | 138 | 139 | 148 | 149 | 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /android/src/main/res/layout/photo_album_activity_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /android/src/main/res/mipmap-xxhdpi/camera_change_crecord_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/android/src/main/res/mipmap-xxhdpi/camera_change_crecord_icon.png -------------------------------------------------------------------------------- /android/src/main/res/mipmap-xxhdpi/camera_flash_open_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/android/src/main/res/mipmap-xxhdpi/camera_flash_open_icon.png -------------------------------------------------------------------------------- /android/src/main/res/mipmap-xxhdpi/camera_record_finish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/android/src/main/res/mipmap-xxhdpi/camera_record_finish.png -------------------------------------------------------------------------------- /android/src/main/res/mipmap-xxhdpi/camera_record_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/android/src/main/res/mipmap-xxhdpi/camera_record_icon.png -------------------------------------------------------------------------------- /android/src/main/res/mipmap-xxhdpi/camera_select_photo_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/android/src/main/res/mipmap-xxhdpi/camera_select_photo_icon.png -------------------------------------------------------------------------------- /android/src/main/res/mipmap-xxhdpi/camera_white_back_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/android/src/main/res/mipmap-xxhdpi/camera_white_back_icon.png -------------------------------------------------------------------------------- /android/src/main/res/mipmap-xxhdpi/scanline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/android/src/main/res/mipmap-xxhdpi/scanline.png -------------------------------------------------------------------------------- /android/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #00000000 5 | #ff000000 6 | #30000000 7 | #00000000 8 | #D9ffffff 9 | #10ffffff 10 | -------------------------------------------------------------------------------- /android/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CameraLibrary 3 | 4 | -------------------------------------------------------------------------------- /android/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Exceptions to above rules. 44 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 45 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 84c84fb24914e098667649be04614f6ea19d689c 8 | channel: dev 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # flutter_custom_camera_pugin_example 2 | 3 | Demonstrates how to use the flutter_custom_camera_pugin plugin. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 28 29 | 30 | lintOptions { 31 | disable 'InvalidPackage' 32 | } 33 | 34 | defaultConfig { 35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 36 | applicationId "com.studyyoun.camera.flutter_custom_camera_pugin_example" 37 | minSdkVersion 16 38 | targetSdkVersion 28 39 | versionCode flutterVersionCode.toInteger() 40 | versionName flutterVersionName 41 | } 42 | 43 | buildTypes { 44 | release { 45 | // TODO: Add your own signing config for the release build. 46 | // Signing with the debug keys for now, so `flutter run --release` works. 47 | signingConfig signingConfigs.debug 48 | } 49 | } 50 | } 51 | 52 | flutter { 53 | source '../..' 54 | } 55 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 12 | 19 | 23 | 27 | 32 | 36 | 37 | 38 | 39 | 40 | 41 | 43 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/studyyoun/camera/flutter_custom_camera_pugin_example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.studyyoun.camera.flutter_custom_camera_pugin_example; 2 | 3 | import io.flutter.embedding.android.FlutterActivity; 4 | 5 | public class MainActivity extends FlutterActivity { 6 | } 7 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.5.0' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | jcenter() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Flutter Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | include ':app' 6 | 7 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 8 | def properties = new Properties() 9 | 10 | assert localPropertiesFile.exists() 11 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 12 | 13 | def flutterSdkPath = properties.getProperty("flutter.sdk") 14 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 15 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 16 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def parse_KV_file(file, separator='=') 14 | file_abs_path = File.expand_path(file) 15 | if !File.exists? file_abs_path 16 | return []; 17 | end 18 | generated_key_values = {} 19 | skip_line_start_symbols = ["#", "/"] 20 | File.foreach(file_abs_path) do |line| 21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 22 | plugin = line.split(pattern=separator) 23 | if plugin.length == 2 24 | podname = plugin[0].strip() 25 | path = plugin[1].strip() 26 | podpath = File.expand_path("#{path}", file_abs_path) 27 | generated_key_values[podname] = podpath 28 | else 29 | puts "Invalid plugin specification: #{line}" 30 | end 31 | end 32 | generated_key_values 33 | end 34 | 35 | target 'Runner' do 36 | # Flutter Pod 37 | 38 | copied_flutter_dir = File.join(__dir__, 'Flutter') 39 | copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') 40 | copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') 41 | unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) 42 | # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. 43 | # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. 44 | # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. 45 | 46 | generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') 47 | unless File.exist?(generated_xcode_build_settings_path) 48 | raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" 49 | end 50 | generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) 51 | cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; 52 | 53 | unless File.exist?(copied_framework_path) 54 | FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) 55 | end 56 | unless File.exist?(copied_podspec_path) 57 | FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) 58 | end 59 | end 60 | 61 | # Keep pod path relative so it can be checked into Podfile.lock. 62 | pod 'Flutter', :path => 'Flutter' 63 | 64 | # Plugin Pods 65 | 66 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 67 | # referring to absolute paths on developers' machines. 68 | system('rm -rf .symlinks') 69 | system('mkdir -p .symlinks/plugins') 70 | plugin_pods = parse_KV_file('../.flutter-plugins') 71 | plugin_pods.each do |name, path| 72 | symlink = File.join('.symlinks', 'plugins', name) 73 | File.symlink(path, symlink) 74 | pod name, :path => File.join(symlink, 'ios') 75 | end 76 | end 77 | 78 | post_install do |installer| 79 | installer.pods_project.targets.each do |target| 80 | target.build_configurations.each do |config| 81 | config.build_settings['ENABLE_BITCODE'] = 'NO' 82 | end 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - flutter_custom_camera_pugin (0.0.1): 4 | - Flutter 5 | 6 | DEPENDENCIES: 7 | - Flutter (from `Flutter`) 8 | - flutter_custom_camera_pugin (from `.symlinks/plugins/flutter_custom_camera_pugin/ios`) 9 | 10 | EXTERNAL SOURCES: 11 | Flutter: 12 | :path: Flutter 13 | flutter_custom_camera_pugin: 14 | :path: ".symlinks/plugins/flutter_custom_camera_pugin/ios" 15 | 16 | SPEC CHECKSUMS: 17 | Flutter: 0e3d915762c693b495b44d77113d4970485de6ec 18 | flutter_custom_camera_pugin: 7566d6050ecc4e2b01ef892a0b1a36ee7a2da5d7 19 | 20 | PODFILE CHECKSUM: f32fb4e7c14f8b3ca19a369d7be425dd9241af27 21 | 22 | COCOAPODS: 1.9.3 23 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Latest 7 | PreviewsEnabled 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "相机@2x.png", 5 | "idiom" : "iphone", 6 | "scale" : "2x", 7 | "size" : "20x20" 8 | }, 9 | { 10 | "filename" : "相机@3x.png", 11 | "idiom" : "iphone", 12 | "scale" : "3x", 13 | "size" : "20x20" 14 | }, 15 | { 16 | "filename" : "相机-1.png", 17 | "idiom" : "iphone", 18 | "scale" : "1x", 19 | "size" : "29x29" 20 | }, 21 | { 22 | "filename" : "相机@2x-2.png", 23 | "idiom" : "iphone", 24 | "scale" : "2x", 25 | "size" : "29x29" 26 | }, 27 | { 28 | "filename" : "相机@3x-1.png", 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "29x29" 32 | }, 33 | { 34 | "filename" : "相机@2x-5.png", 35 | "idiom" : "iphone", 36 | "scale" : "2x", 37 | "size" : "40x40" 38 | }, 39 | { 40 | "filename" : "相机@3x-2.png", 41 | "idiom" : "iphone", 42 | "scale" : "3x", 43 | "size" : "40x40" 44 | }, 45 | { 46 | "filename" : "相机@2x-6.png", 47 | "idiom" : "iphone", 48 | "scale" : "2x", 49 | "size" : "60x60" 50 | }, 51 | { 52 | "filename" : "相机@3x-3.png", 53 | "idiom" : "iphone", 54 | "scale" : "3x", 55 | "size" : "60x60" 56 | }, 57 | { 58 | "filename" : "相机.png", 59 | "idiom" : "ipad", 60 | "scale" : "1x", 61 | "size" : "20x20" 62 | }, 63 | { 64 | "filename" : "相机@2x-1.png", 65 | "idiom" : "ipad", 66 | "scale" : "2x", 67 | "size" : "20x20" 68 | }, 69 | { 70 | "filename" : "相机-2.png", 71 | "idiom" : "ipad", 72 | "scale" : "1x", 73 | "size" : "29x29" 74 | }, 75 | { 76 | "filename" : "相机@2x-3.png", 77 | "idiom" : "ipad", 78 | "scale" : "2x", 79 | "size" : "29x29" 80 | }, 81 | { 82 | "filename" : "相机-3.png", 83 | "idiom" : "ipad", 84 | "scale" : "1x", 85 | "size" : "40x40" 86 | }, 87 | { 88 | "filename" : "相机@2x-4.png", 89 | "idiom" : "ipad", 90 | "scale" : "2x", 91 | "size" : "40x40" 92 | }, 93 | { 94 | "filename" : "相机-4.png", 95 | "idiom" : "ipad", 96 | "scale" : "1x", 97 | "size" : "76x76" 98 | }, 99 | { 100 | "filename" : "相机@2x-7.png", 101 | "idiom" : "ipad", 102 | "scale" : "2x", 103 | "size" : "76x76" 104 | }, 105 | { 106 | "idiom" : "ipad", 107 | "scale" : "2x", 108 | "size" : "83.5x83.5" 109 | }, 110 | { 111 | "idiom" : "ios-marketing", 112 | "scale" : "1x", 113 | "size" : "1024x1024" 114 | } 115 | ], 116 | "info" : { 117 | "author" : "xcode", 118 | "version" : 1 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机-1.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机-2.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机-3.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机-4.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@2x-1.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@2x-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@2x-2.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@2x-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@2x-3.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@2x-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@2x-4.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@2x-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@2x-5.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@2x-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@2x-6.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@2x-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@2x-7.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@3x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@3x-1.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@3x-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@3x-2.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@3x-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@3x-3.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/相机@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutter_custom_camera_pugin_example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | NSMicrophoneUsageDescription 45 | App需要您的同意,才能访问麦克风 46 | NSLocationUsageDescription 47 | App需要您的同意,才能访问位置 48 | NSLocationWhenInUseUsageDescription 49 | App需要您的同意,才能在使用期间访问位置 50 | NSLocationAlwaysUsageDescription 51 | App需要您的同意,才能始终访问位置 52 | NSCalendarsUsageDescription 53 | App需要您的同意,才能访问日历 54 | NSRemindersUsageDescription 55 | App需要您的同意,才能访问提醒事项 56 | NSMotionUsageDescription 57 | App需要您的同意,才能访问运动与健身 58 | NSHealthUpdateUsageDescription 59 | App需要您的同意,才能访问健康更新 60 | NSHealthShareUsageDescription 61 | App需要您的同意,才能访问健康分享 62 | NSBluetoothPeripheralUsageDescription 63 | App需要您的同意,才能访问蓝牙 64 | NSAppleMusicUsageDescription 65 | App需要您的同意,才能访问媒体资料库 66 | NSCameraUsageDescription 67 | 请允许APP访问您的相机 68 | NSPhotoLibraryAddUsageDescription 69 | 请允许APP保存图片到相册 70 | NSPhotoLibraryUsageDescription 71 | 请允许APP访问您的相册 72 | 73 | 74 | -------------------------------------------------------------------------------- /example/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'dart:async'; 5 | 6 | import 'package:flutter/services.dart'; 7 | import 'package:flutter_custom_camera_pugin/flutter_custom_camera_pugin.dart'; 8 | 9 | void main() { 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatefulWidget { 14 | @override 15 | _MyAppState createState() => _MyAppState(); 16 | } 17 | 18 | class _MyAppState extends State { 19 | CameraResultInfo _cameraResultInfo; 20 | 21 | @override 22 | void initState() { 23 | super.initState(); 24 | } 25 | 26 | Future testPlugin() async { 27 | CameraResultInfo platformVersion; 28 | 29 | try { 30 | platformVersion = await FlutterCustomCameraPugin.testPugin(); 31 | } on PlatformException { 32 | platformVersion = CameraResultInfo.fromError(); 33 | } 34 | if (!mounted) return; 35 | 36 | imageFile = File("/var/mobile/Containers/Data/Application/395710CE-46E3-47EB-9D36-4C2697F91C83/Documents/1599919466them.png"); 37 | setState(() { 38 | _cameraResultInfo = platformVersion; 39 | }); 40 | } 41 | 42 | @override 43 | Widget build(BuildContext context) { 44 | return MaterialApp( 45 | home: Scaffold( 46 | appBar: AppBar( 47 | title: const Text(' Flutter 自定义相机插件 '), 48 | ), 49 | body:SingleChildScrollView(child: Column( 50 | crossAxisAlignment: CrossAxisAlignment.center, 51 | children: [ 52 | Text( 53 | 'Running on: ${_cameraResultInfo != null ? _cameraResultInfo.toString() : ''}\n'), 54 | 55 | // Image.asset("icons/camera_record_icon.png",package: "flutter_custom_camera_pugin",), 56 | OutlineButton( 57 | child: Text('测试下'), 58 | onPressed: () { 59 | testPlugin(); 60 | }, 61 | ), 62 | OutlineButton( 63 | child: Text('清除下数据'), 64 | onPressed: () { 65 | setState(() { 66 | _cameraResultInfo = null; 67 | imageFile = null; 68 | }); 69 | }, 70 | ), 71 | OutlineButton( 72 | child: Text('打开自定义相机'), 73 | onPressed: () { 74 | openCamera(); 75 | }, 76 | ), 77 | OutlineButton( 78 | child: Text('打开相册'), 79 | onPressed: () { 80 | openPhotoAlbum(); 81 | }, 82 | ), 83 | 84 | OutlineButton( 85 | child: Text('打开系统相机'), 86 | onPressed: () { 87 | openSystemCamera(); 88 | }, 89 | ), 90 | OutlineButton( 91 | child: Text('打开系统相册'), 92 | onPressed: () { 93 | openSystemPhotoAlbum(); 94 | }, 95 | ), 96 | OutlineButton( 97 | child: Text('打开系统相机相册选择弹框'), 98 | onPressed: () { 99 | openSystemAlert(); 100 | }, 101 | ), 102 | 103 | imageFile == null 104 | ? Text("图片预览区域") 105 | : Image.file( 106 | imageFile, 107 | width: 375, 108 | fit: BoxFit.fitWidth, 109 | ), 110 | ], 111 | ),), 112 | ), 113 | ); 114 | } 115 | 116 | File imageFile; 117 | 118 | ///打开相机 119 | ///如 你点击一个按钮 120 | void openCamera() async { 121 | 122 | ///相机使用配置参数 123 | CameraConfigOptions options = new CameraConfigOptions(); 124 | 125 | ///默认自定义相册是否显示 相册切换 126 | options.isShowSelectCamera = true; 127 | 128 | ///默认自定义相册是否显示 前后镜头切换 129 | options.isShowPhotoAlbum = true; 130 | 131 | ///默认自定义相册是否显示 闪光灯开关按钮 132 | options.isShowFlashButtonCamera = true; 133 | /// 是否预览照片 如拍照完成 或者相册选择完成 默认为 true 预览 134 | options.isPreviewImage = false; 135 | ///调起自定义相机 136 | ///拍照的返回结果 137 | CameraResultInfo resultInfo = 138 | await FlutterCustomCameraPugin.openCamera(cameraConfigOptions: options); 139 | 140 | if (resultInfo.code == 200) { 141 | imageFile = new File(resultInfo.data["lImageUrl"]); 142 | } else if (resultInfo.code == 201) { 143 | ///201 是拍照取消 如点击了关闭按钮 144 | ///或者是 Android 手机的后退按钮 145 | } 146 | 147 | _cameraResultInfo = resultInfo; 148 | 149 | setState(() {}); 150 | } 151 | 152 | ///考虑自定义一下 开发中 153 | void openCustomCamera() async {} 154 | 155 | ///打开相册 156 | void openPhotoAlbum() async { 157 | /// 相册的选择返回结果 158 | /// 选择成功与取消都会回调 159 | CameraResultInfo resultInfo =await FlutterCustomCameraPugin.openPhotoAlbum(); 160 | if (resultInfo.code == 200) { 161 | imageFile = new File(resultInfo.data["lImageUrl"]); 162 | } 163 | 164 | _cameraResultInfo =resultInfo ; 165 | setState(() {}); 166 | } 167 | 168 | void openSystemCamera() async{ 169 | ///相机使用配置参数 170 | CameraConfigOptions options = new CameraConfigOptions(); 171 | options.isPreviewImage = false; 172 | CameraResultInfo resultInfo = 173 | await FlutterCustomCameraPugin.openSystemCamera(cameraConfigOptions: options); 174 | 175 | if (resultInfo.code == 200) { 176 | String imageUrl =resultInfo.data["lImageUrl"]; 177 | print("openSystemCamera "+imageUrl.toString()); 178 | imageFile = new File(imageUrl); 179 | } else if (resultInfo.code == 201) { 180 | ///201 是拍照取消 如点击了关闭按钮 181 | ///或者是 Android 手机的后退按钮 182 | } 183 | 184 | setState(() {}); 185 | } 186 | 187 | void openSystemPhotoAlbum() async { 188 | /// 相册的选择返回结果 189 | /// 选择成功与取消都会回调 190 | CameraResultInfo resultInfo =await FlutterCustomCameraPugin.openSystemPhotoAlbum(); 191 | if (resultInfo.code == 200) { 192 | imageFile = new File(resultInfo.data["lImageUrl"]); 193 | } 194 | 195 | _cameraResultInfo =resultInfo ; 196 | setState(() {}); 197 | } 198 | 199 | void openSystemAlert() async { 200 | /// 相册的选择返回结果 201 | /// 选择成功与取消都会回调 202 | CameraResultInfo resultInfo =await FlutterCustomCameraPugin.openSystemAlert(); 203 | 204 | if (resultInfo.code == 200) { 205 | imageFile = new File(resultInfo.data["lImageUrl"]); 206 | } 207 | 208 | 209 | _cameraResultInfo =resultInfo ; 210 | setState(() {}); 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.flutter-io.cn" 9 | source: hosted 10 | version: "2.4.1" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.flutter-io.cn" 16 | source: hosted 17 | version: "2.0.0" 18 | charcode: 19 | dependency: transitive 20 | description: 21 | name: charcode 22 | url: "https://pub.flutter-io.cn" 23 | source: hosted 24 | version: "1.1.3" 25 | clock: 26 | dependency: transitive 27 | description: 28 | name: clock 29 | url: "https://pub.flutter-io.cn" 30 | source: hosted 31 | version: "1.0.1" 32 | collection: 33 | dependency: transitive 34 | description: 35 | name: collection 36 | url: "https://pub.flutter-io.cn" 37 | source: hosted 38 | version: "1.14.12" 39 | cupertino_icons: 40 | dependency: "direct main" 41 | description: 42 | name: cupertino_icons 43 | url: "https://pub.flutter-io.cn" 44 | source: hosted 45 | version: "0.1.3" 46 | fake_async: 47 | dependency: transitive 48 | description: 49 | name: fake_async 50 | url: "https://pub.flutter-io.cn" 51 | source: hosted 52 | version: "1.1.0" 53 | flutter: 54 | dependency: "direct main" 55 | description: flutter 56 | source: sdk 57 | version: "0.0.0" 58 | flutter_custom_camera_pugin: 59 | dependency: "direct main" 60 | description: 61 | path: ".." 62 | relative: true 63 | source: path 64 | version: "0.0.4" 65 | flutter_test: 66 | dependency: "direct dev" 67 | description: flutter 68 | source: sdk 69 | version: "0.0.0" 70 | matcher: 71 | dependency: transitive 72 | description: 73 | name: matcher 74 | url: "https://pub.flutter-io.cn" 75 | source: hosted 76 | version: "0.12.6" 77 | meta: 78 | dependency: transitive 79 | description: 80 | name: meta 81 | url: "https://pub.flutter-io.cn" 82 | source: hosted 83 | version: "1.1.8" 84 | path: 85 | dependency: transitive 86 | description: 87 | name: path 88 | url: "https://pub.flutter-io.cn" 89 | source: hosted 90 | version: "1.7.0" 91 | sky_engine: 92 | dependency: transitive 93 | description: flutter 94 | source: sdk 95 | version: "0.0.99" 96 | source_span: 97 | dependency: transitive 98 | description: 99 | name: source_span 100 | url: "https://pub.flutter-io.cn" 101 | source: hosted 102 | version: "1.7.0" 103 | stack_trace: 104 | dependency: transitive 105 | description: 106 | name: stack_trace 107 | url: "https://pub.flutter-io.cn" 108 | source: hosted 109 | version: "1.9.3" 110 | stream_channel: 111 | dependency: transitive 112 | description: 113 | name: stream_channel 114 | url: "https://pub.flutter-io.cn" 115 | source: hosted 116 | version: "2.0.0" 117 | string_scanner: 118 | dependency: transitive 119 | description: 120 | name: string_scanner 121 | url: "https://pub.flutter-io.cn" 122 | source: hosted 123 | version: "1.0.5" 124 | term_glyph: 125 | dependency: transitive 126 | description: 127 | name: term_glyph 128 | url: "https://pub.flutter-io.cn" 129 | source: hosted 130 | version: "1.1.0" 131 | test_api: 132 | dependency: transitive 133 | description: 134 | name: test_api 135 | url: "https://pub.flutter-io.cn" 136 | source: hosted 137 | version: "0.2.15" 138 | typed_data: 139 | dependency: transitive 140 | description: 141 | name: typed_data 142 | url: "https://pub.flutter-io.cn" 143 | source: hosted 144 | version: "1.1.6" 145 | vector_math: 146 | dependency: transitive 147 | description: 148 | name: vector_math 149 | url: "https://pub.flutter-io.cn" 150 | source: hosted 151 | version: "2.0.8" 152 | sdks: 153 | dart: ">=2.7.0 <3.0.0" 154 | flutter: ">=1.10.0" 155 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_custom_camera_pugin_example 2 | description: Demonstrates how to use the flutter_custom_camera_pugin plugin. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | environment: 9 | sdk: ">=2.7.0 <3.0.0" 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | 15 | flutter_custom_camera_pugin: 16 | # When depending on this package from a real application you should use: 17 | # flutter_custom_camera_pugin: ^x.y.z 18 | # See https://dart.dev/tools/pub/dependencies#version-constraints 19 | # The example app is bundled with the plugin so we use a path dependency on 20 | # the parent directory to use the current plugin's version. 21 | path: ../ 22 | 23 | # The following adds the Cupertino Icons font to your application. 24 | # Use with the CupertinoIcons class for iOS style icons. 25 | cupertino_icons: ^0.1.3 26 | 27 | dev_dependencies: 28 | flutter_test: 29 | sdk: flutter 30 | 31 | # For information on the generic Dart part of this file, see the 32 | # following page: https://dart.dev/tools/pub/pubspec 33 | 34 | # The following section is specific to Flutter. 35 | flutter: 36 | 37 | # The following line ensures that the Material Icons font is 38 | # included with your application, so that you can use the icons in 39 | # the material Icons class. 40 | uses-material-design: true 41 | 42 | # To add assets to your application, add an assets section, like this: 43 | # assets: 44 | # - images/a_dot_burr.jpeg 45 | # - images/a_dot_ham.jpeg 46 | 47 | # An image asset can refer to one or more resolution-specific "variants", see 48 | # https://flutter.dev/assets-and-images/#resolution-aware. 49 | 50 | # For details regarding adding assets from package dependencies, see 51 | # https://flutter.dev/assets-and-images/#from-packages 52 | 53 | # To add custom fonts to your application, add a fonts section here, 54 | # in this "flutter" section. Each entry in this list should have a 55 | # "family" key with the font family name, and a "fonts" key with a 56 | # list giving the asset and other descriptors for the font. For 57 | # example: 58 | # fonts: 59 | # - family: Schyler 60 | # fonts: 61 | # - asset: fonts/Schyler-Regular.ttf 62 | # - asset: fonts/Schyler-Italic.ttf 63 | # style: italic 64 | # - family: Trajan Pro 65 | # fonts: 66 | # - asset: fonts/TrajanPro.ttf 67 | # - asset: fonts/TrajanPro_Bold.ttf 68 | # weight: 700 69 | # 70 | # For details regarding fonts from package dependencies, 71 | # see https://flutter.dev/custom-fonts/#from-packages 72 | -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:flutter_custom_camera_pugin_example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Verify Platform version', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(MyApp()); 17 | 18 | // Verify that platform version is retrieved. 19 | expect( 20 | find.byWidgetPredicate( 21 | (Widget widget) => widget is Text && 22 | widget.data.startsWith('Running on:'), 23 | ), 24 | findsOneWidget, 25 | ); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /flutter_custom_camera_pugin.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /icons/camera_change_crecord_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/icons/camera_change_crecord_icon.png -------------------------------------------------------------------------------- /icons/camera_flash_open_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/icons/camera_flash_open_icon.png -------------------------------------------------------------------------------- /icons/camera_record_finish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/icons/camera_record_finish.png -------------------------------------------------------------------------------- /icons/camera_record_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/icons/camera_record_icon.png -------------------------------------------------------------------------------- /icons/camera_select_photo_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/icons/camera_select_photo_icon.png -------------------------------------------------------------------------------- /icons/camera_white_back_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/icons/camera_white_back_icon.png -------------------------------------------------------------------------------- /icons/scanline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/icons/scanline.png -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vagrant/ 3 | .sconsign.dblite 4 | .svn/ 5 | 6 | .DS_Store 7 | *.swp 8 | profile 9 | 10 | DerivedData/ 11 | build/ 12 | GeneratedPluginRegistrant.h 13 | GeneratedPluginRegistrant.m 14 | 15 | .generated/ 16 | 17 | *.pbxuser 18 | *.mode1v3 19 | *.mode2v3 20 | *.perspectivev3 21 | 22 | !default.pbxuser 23 | !default.mode1v3 24 | !default.mode2v3 25 | !default.perspectivev3 26 | 27 | xcuserdata 28 | 29 | *.moved-aside 30 | 31 | *.pyc 32 | *sync/ 33 | Icon? 34 | .tags* 35 | 36 | /Flutter/Generated.xcconfig 37 | /Flutter/flutter_export_environment.sh -------------------------------------------------------------------------------- /ios/Classes/CameraConfigOption.h: -------------------------------------------------------------------------------- 1 | // 2 | // CameraConfigOption.h 3 | // flutter_custom_camera_pugin 4 | // 5 | // Created by androidlongs on 2020/9/12. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface CameraConfigOption : NSObject 13 | ///默认自定义相册是否显示 相册切换 14 | @property(assign,nonatomic) BOOL isShowPhotoAlbum ; 15 | 16 | ///默认自定义相册是否显示 前后镜头切换 17 | @property(assign,nonatomic) BOOL isShowSelectCamera ; 18 | 19 | ///默认自定义相册是否显示 闪光灯开关按钮 20 | @property(assign,nonatomic) BOOL isShowFlashButtonCamera; 21 | 22 | /// 是否预览照片 如拍照完成 或者相册选择完成 23 | @property(assign,nonatomic) BOOL isPreviewImage ; 24 | 25 | /// 是否启动裁剪功能 如拍照完成 或者相册选择完成 26 | @property(assign,nonatomic) BOOL isCropImage ; 27 | /// 是否显示提示 28 | @property(assign,nonatomic) BOOL isShowToast ; 29 | 30 | @property(strong,nonatomic) NSArray *iconsList; 31 | @property(strong,nonatomic) NSArray *imageAssetList; 32 | 33 | -(instancetype)initWithDict:(NSDictionary *)result; 34 | +(instancetype)userWithDict:(NSDictionary *)dict; 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /ios/Classes/CameraConfigOption.m: -------------------------------------------------------------------------------- 1 | // 2 | // CameraConfigOption.m 3 | // flutter_custom_camera_pugin 4 | // 5 | // Created by androidlongs on 2020/9/12. 6 | // 7 | 8 | #import "CameraConfigOption.h" 9 | 10 | @implementation CameraConfigOption 11 | 12 | -(instancetype)initWithDict:(NSDictionary *)result{ 13 | if (self=[super init]) { 14 | 15 | 16 | /* 17 | 18 | ///默认自定义相册是否显示 相册切换 19 | public boolean isShowPhotoAlbum = true; 20 | 21 | ///默认自定义相册是否显示 前后镜头切换 22 | public boolean isShowSelectCamera = true; 23 | 24 | ///默认自定义相册是否显示 闪光灯开关按钮 25 | public boolean isShowFlashButtonCamera = true; 26 | 27 | /// 是否预览照片 如拍照完成 或者相册选择完成 28 | public boolean isPreviewImage = true; 29 | 30 | /// 是否启动裁剪功能 如拍照完成 或者相册选择完成 31 | public boolean isCropImage = false; 32 | /// 是否显示提示 33 | public boolean isShowToast = true ; 34 | */ 35 | 36 | _iconsList =[result objectForKey:@"iconsList"]; 37 | 38 | _isShowPhotoAlbum = [[result objectForKey:@"isShowPhotoAlbum"] boolValue]; 39 | _isShowSelectCamera = [[result objectForKey:@"isShowSelectCamera"] boolValue]; 40 | _isShowFlashButtonCamera = [[result objectForKey:@"isShowFlashButtonCamera"] boolValue]; 41 | 42 | _isPreviewImage = [[result objectForKey:@"isPreviewImage"] boolValue]; 43 | _isCropImage = [[result objectForKey:@"isCropImage"] boolValue]; 44 | _isShowToast = [[result objectForKey:@"isShowToast"] boolValue]; 45 | 46 | 47 | 48 | 49 | } 50 | return self; 51 | } 52 | +(instancetype)userWithDict:(NSDictionary *)dict{ 53 | return [[self alloc] initWithDict:dict]; 54 | } 55 | @end 56 | -------------------------------------------------------------------------------- /ios/Classes/CameraUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // CameraUtils.h 3 | // flutter_custom_camera_pugin 4 | // 5 | // Created by androidlongs on 2020/9/12. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface CameraUtils : NSObject 13 | 14 | 15 | +(void) nextWithImageUrl:(NSString*)imageUrl; 16 | +(void) cancle:(NSInteger) flag; 17 | 18 | @end 19 | 20 | NS_ASSUME_NONNULL_END 21 | -------------------------------------------------------------------------------- /ios/Classes/CameraUtils.m: -------------------------------------------------------------------------------- 1 | // 2 | // CameraUtils.m 3 | // flutter_custom_camera_pugin 4 | // 5 | // Created by androidlongs on 2020/9/12. 6 | // 7 | 8 | #import "CameraUtils.h" 9 | 10 | @implementation CameraUtils 11 | 12 | +(void)nextWithImageUrl:(NSString *)imageUrl{ 13 | NSMutableDictionary *dict = [[NSMutableDictionary alloc]init]; 14 | [dict setObject:imageUrl forKey:@"filePath"]; 15 | [dict setObject:[NSNumber numberWithInt:200] forKey:@"code"]; 16 | //发送消息 17 | NSNotification *notification = [NSNotification notificationWithName:@"NOTIFICATION_NAME" 18 | object:dict]; 19 | [[NSNotificationCenter defaultCenter] postNotification:notification]; 20 | [UIApplication.sharedApplication.delegate.window.rootViewController dismissViewControllerAnimated:NO completion:^{ 21 | }]; 22 | } 23 | 24 | +(void)cancle:(NSInteger)flag{ 25 | 26 | } 27 | @end 28 | -------------------------------------------------------------------------------- /ios/Classes/FlutterCustomCameraPuginPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | 5 | 6 | #define UIScreen_Height [UIScreen mainScreen].bounds.size.height 7 | #define UIScreen_Width [UIScreen mainScreen].bounds.size.Width 8 | 9 | @interface FlutterCustomCameraPuginPlugin : NSObject 10 | @end 11 | -------------------------------------------------------------------------------- /ios/Classes/FlutterCustomCameraPuginPlugin.m: -------------------------------------------------------------------------------- 1 | #import "FlutterCustomCameraPuginPlugin.h" 2 | #import "CameraViewController.h" 3 | #import 4 | #import "CustomeAlertView.h" 5 | #import "CameraConfigOption.h" 6 | #import "LeePhotoOrAlbumImagePicker.h" 7 | 8 | @interface FlutterCustomCameraPuginPlugin () 9 | @property (nonatomic, strong) FlutterReply flutterReply ; 10 | @end 11 | 12 | @implementation FlutterCustomCameraPuginPlugin{ 13 | FlutterBasicMessageChannel* messageChannel; 14 | } 15 | 16 | 17 | //注册插件的方法 18 | + (void)registerWithRegistrar:(NSObject*)registrar { 19 | FlutterMethodChannel* channel = [FlutterMethodChannel 20 | methodChannelWithName:@"flutter_custom_camera_pugin" 21 | binaryMessenger:[registrar messenger]]; 22 | FlutterCustomCameraPuginPlugin* instance = [[FlutterCustomCameraPuginPlugin alloc] init]; 23 | [registrar addMethodCallDelegate:instance channel:channel]; 24 | 25 | //自定义的消息通道 26 | //FlutterBasicMessageChannel 与Flutter 之间的双向通信 27 | [instance basicMessageChannelFunction:registrar]; 28 | 29 | 30 | } 31 | 32 | // ios 原生通知消息 用于数据传递 33 | - (void)execute:(NSNotification *)notification { 34 | //do something when received notification 35 | //notification.name is @"NOTIFICATION_NAME" 36 | if(notification.object){ 37 | NSDictionary *nDict =notification.object; 38 | NSMutableDictionary *dic = [NSMutableDictionary dictionary]; 39 | 40 | NSInteger code = [[nDict objectForKey:@"code"] intValue] ; 41 | 42 | if(code == 200){ 43 | NSLog(@"发送成功消息"); 44 | NSDictionary *dict = [NSDictionary dictionaryWithObject:nDict[@"filePath"] forKey:@"lImageUrl"]; 45 | [dic setObject:dict forKey:@"data"]; 46 | [dic setObject:@"原生 ios 返回给flutter的数据" forKey:@"message"]; 47 | [dic setObject: [NSNumber numberWithInt:200] forKey:@"code"]; 48 | //需要注意的是 这个方法只能回调一次 49 | self.flutterReply(dic); 50 | }else if(code == 204){ 51 | //自定义相机页面显示打开相册 52 | [self openCamer:1 andWithOptions:nil andWithRegistrar:nil]; 53 | }else{ 54 | NSDictionary *dict = [NSDictionary dictionary]; 55 | [dic setObject:dict forKey:@"data"]; 56 | [dic setObject:@"相机拍照取消" forKey:@"message"]; 57 | [dic setObject: [NSNumber numberWithInt:201] forKey:@"code"]; 58 | //需要注意的是 这个方法只能回调一次 59 | self.flutterReply(dic); 60 | } 61 | 62 | } 63 | } 64 | - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { 65 | if ([@"getPlatformVersion" isEqualToString:call.method]) { 66 | result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]); 67 | } else { 68 | result(FlutterMethodNotImplemented); 69 | } 70 | } 71 | 72 | -(void) basicMessageChannelFunction:(NSObject*)registrar { 73 | 74 | // 注册观察者: 75 | [[NSNotificationCenter defaultCenter] addObserver:self 76 | selector:@selector(execute:) 77 | name:@"NOTIFICATION_NAME" 78 | object:nil]; 79 | // 初始化定义 80 | // flutter_and_native_100 j 81 | // Flutter 调用 ios 在这里 82 | messageChannel = [FlutterBasicMessageChannel messageChannelWithName:@"flutter_and_native_custom_100" binaryMessenger:[registrar messenger]]; 83 | 84 | __weak typeof(self) weakSelf = self; 85 | // 接收消息监听 86 | [messageChannel setMessageHandler:^(id message, FlutterReply callback) { 87 | weakSelf.flutterReply = callback ; 88 | NSString *method=message[@"method"]; 89 | //相机配置参数 90 | NSDictionary *optionsDict=message[@"options"]; 91 | if ([method isEqualToString:@"test"]) { 92 | NSLog(@"flutter 调用到了 ios test"); 93 | NSMutableDictionary *dic = [NSMutableDictionary dictionary]; 94 | [dic setObject:@"原生 ios 返回给flutter的数据" forKey:@"message"]; 95 | [dic setObject: [NSNumber numberWithInt:200] forKey:@"code"]; 96 | //需要注意的是 这个方法只能回调一次 97 | callback(dic); 98 | }else if ([method isEqualToString:@"openCamera"]) { 99 | [weakSelf openCamer:0 andWithOptions:optionsDict andWithRegistrar:registrar]; 100 | }else if ([method isEqualToString:@"openPhotoAlbum"]) { 101 | [weakSelf openCamer:1 andWithOptions:optionsDict andWithRegistrar:registrar]; 102 | }else if ([method isEqualToString:@"openSystemCamera"]) { 103 | 104 | [weakSelf openCamer:2 andWithOptions:optionsDict andWithRegistrar:registrar]; 105 | }else if ([method isEqualToString:@"openSystemAlert"]) { 106 | 107 | [weakSelf openCamer:3 andWithOptions:optionsDict andWithRegistrar:registrar]; 108 | } 109 | }]; 110 | 111 | 112 | 113 | 114 | } 115 | 116 | -(void)openCamer:(NSInteger) flag andWithOptions:(NSDictionary*) optionsDict andWithRegistrar:(NSObject*)registrar { 117 | CameraConfigOption * cameraOptions = [[CameraConfigOption alloc]initWithDict:optionsDict]; 118 | if (registrar!=nil) { 119 | NSArray *imageArray = cameraOptions.iconsList; 120 | NSMutableArray *assetImageArray = [[NSMutableArray alloc]init]; 121 | for (int i=0; i 10 | 11 | @interface CustomeAlertView : NSObject 12 | 13 | +(instancetype)shareView; 14 | -(void)showCustomeAlertViewWithMessage:(NSString *)message; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /ios/Classes/alert/CustomeAlertView.m: -------------------------------------------------------------------------------- 1 | // 2 | // CustomeAlertView.m 3 | // GPUPhoto 4 | // 5 | // Created by ios2chen on 2017/7/12. 6 | // Copyright © 2017年 Lfy. All rights reserved. 7 | // 8 | 9 | #import "CustomeAlertView.h" 10 | #import 11 | 12 | @interface CustomeAlertView () 13 | 14 | @property (nonatomic, strong) UIView *clearBackGroundView; 15 | 16 | @end 17 | @implementation CustomeAlertView 18 | 19 | 20 | static CustomeAlertView *alertView = nil; 21 | 22 | +(instancetype)shareView{ 23 | 24 | static dispatch_once_t onceToken; 25 | dispatch_once(&onceToken, ^{ 26 | alertView = [[CustomeAlertView alloc]init]; 27 | 28 | }); 29 | 30 | return alertView; 31 | } 32 | 33 | +(instancetype)allocWithZone:(struct _NSZone *)zone{ 34 | static dispatch_once_t onceToken; 35 | dispatch_once(&onceToken, ^{ 36 | alertView = [super allocWithZone:zone]; 37 | }); 38 | return alertView; 39 | } 40 | 41 | -(id)copyWithZone:(NSZone *)zone{ 42 | return alertView; 43 | } 44 | 45 | -(void)showCustomeAlertViewWithMessage:(NSString *)message{ 46 | 47 | 48 | float maxWidth = [UIScreen mainScreen].bounds.size.width-100; 49 | 50 | self.clearBackGroundView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)]; 51 | self.clearBackGroundView.backgroundColor = [UIColor clearColor]; 52 | UIWindow *window = [UIApplication sharedApplication].keyWindow; 53 | [window addSubview:self.clearBackGroundView]; 54 | 55 | UIView *middleAlphaView = [[UIView alloc]init]; 56 | middleAlphaView.backgroundColor = [UIColor blackColor]; 57 | middleAlphaView.alpha = 0.7; 58 | middleAlphaView.layer.masksToBounds = YES; 59 | middleAlphaView.layer.cornerRadius = 10; 60 | [self.clearBackGroundView addSubview:middleAlphaView]; 61 | 62 | UILabel *messageLabel = [[UILabel alloc]init]; 63 | messageLabel.textColor = [UIColor whiteColor]; 64 | messageLabel.textAlignment = NSTextAlignmentCenter; 65 | messageLabel.font = [UIFont systemFontOfSize:16]; 66 | messageLabel.numberOfLines = 0; 67 | 68 | 69 | 70 | CGSize labelSize = [message boundingRectWithSize:CGSizeMake(MAXFLOAT, 25) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16]} context:nil].size; 71 | 72 | CGSize labelHeightSize = [message boundingRectWithSize:CGSizeMake(maxWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16]} context:nil].size; 73 | 74 | if (labelSize.width<=maxWidth) { 75 | middleAlphaView.frame = CGRectMake(([UIScreen mainScreen].bounds.size.width-labelSize.width-40)/2, ([UIScreen mainScreen].bounds.size.height-45)/2, labelSize.width+40, 45); 76 | messageLabel.frame = CGRectMake(middleAlphaView.frame.origin.x+20, middleAlphaView.frame.origin.y+10, labelSize.width, 25); 77 | 78 | } else{ 79 | middleAlphaView.frame = CGRectMake(30, ([UIScreen mainScreen].bounds.size.height-labelHeightSize.height-20)/2, [UIScreen mainScreen].bounds.size.width-60, labelHeightSize.height+20); 80 | messageLabel.frame = CGRectMake(middleAlphaView.frame.origin.x+20, middleAlphaView.frame.origin.y+10, maxWidth, labelHeightSize.height); 81 | 82 | } 83 | 84 | 85 | messageLabel.text = message; 86 | [self.clearBackGroundView addSubview:messageLabel]; 87 | 88 | [self performSelector:@selector(removeAlertView) withObject:nil afterDelay:1]; 89 | 90 | 91 | 92 | } 93 | 94 | -(void)removeAlertView{ 95 | [self.clearBackGroundView removeFromSuperview]; 96 | self.clearBackGroundView = nil; 97 | 98 | } 99 | 100 | @end 101 | -------------------------------------------------------------------------------- /ios/Classes/camera/CameraShowViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CameraShowViewController.h 3 | // flutter_custom_camera_pugin 4 | // 5 | // Created by androidlongs on 2020/9/12. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface CameraShowViewController : UIViewController 13 | 14 | 15 | @property(strong,nonatomic) NSString * imageUrl; 16 | 17 | //页面标识 201 拍照进来的 18 | // 202 相册进来的 19 | @property(assign,nonatomic) NSInteger pageFlag; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /ios/Classes/camera/CameraShowViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CameraShowViewController.m 3 | // flutter_custom_camera_pugin 4 | // 5 | // Created by androidlongs on 2020/9/12. 6 | // 7 | 8 | #import "CameraShowViewController.h" 9 | #import "CameraUtils.h" 10 | 11 | @interface CameraShowViewController () 12 | @property (unsafe_unretained, nonatomic) IBOutlet UIImageView *showImageView; 13 | @property (unsafe_unretained, nonatomic) IBOutlet UIButton *closeButton; 14 | @property (unsafe_unretained, nonatomic) IBOutlet UIButton *nextButton; 15 | 16 | 17 | 18 | @end 19 | 20 | @implementation CameraShowViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | 26 | UIImage *img = [UIImage imageWithContentsOfFile:@"/var/mobile/Containers/Data/Application/395710CE-46E3-47EB-9D36-4C2697F91C83/Documents/1599919466them.png"]; 27 | 28 | self.showImageView .image = img; 29 | } 30 | - (IBAction)nextButtonAction:(UIButton *)sender { 31 | [self.navigationController popViewControllerAnimated:NO]; 32 | [CameraUtils nextWithImageUrl:self.imageUrl]; 33 | } 34 | 35 | 36 | - (IBAction)cancleButtonAction:(UIButton *)sender { 37 | [CameraUtils cancle:self.pageFlag]; 38 | 39 | [self.navigationController popViewControllerAnimated:NO]; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /ios/Classes/camera/CameraViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CameraViewController.h 3 | // CustomeCamera 4 | // 5 | // Created by ios2chen on 2017/7/20. 6 | // Copyright © 2017年 ios2chen. All rights reserved. 7 | // 8 | #import 9 | #import "CustomeAlertView.h" 10 | #import "CameraConfigOption.h" 11 | #define UIScreen_Height [UIScreen mainScreen].bounds.size.height 12 | #define UIScreen_Width [ UIScreen mainScreen].bounds.size.width 13 | #import 14 | 15 | @interface CameraViewController : UIViewController 16 | 17 | @property(strong,nonatomic) CameraConfigOption * cameraOptions; 18 | 19 | //页面标识 20 | //0 自定义 相机 21 | //1 系统相机 22 | //2 系统相册 23 | // 3 一个弹框选择 24 | @property(assign,nonatomic) NSInteger pageIndex ; 25 | @end 26 | -------------------------------------------------------------------------------- /ios/Classes/camera/LeePhotoOrAlbumImagePicker.h: -------------------------------------------------------------------------------- 1 | // 2 | // LeePhotoOrAlbumImagePicker.h 3 | // flutter_custom_camera_pugin 4 | // 5 | // Created by androidlongs on 2020/9/12. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | typedef void (^LeePhotoOrAlbumImagePickerBlock)(UIImage *image); 12 | @interface LeePhotoOrAlbumImagePicker : NSObject 13 | // 必须创建一个对象才行,才不会释放指针 14 | // 必须先在使用该方法的控制器中初始化 创建这个属性,然后在对象调用如下方法 15 | 16 | /** 17 | 公共方法 选择图片后的图片回掉 18 | 19 | @param controller 使用这个工具的控制器 20 | @param photoBlock 选择图片后的回掉 21 | */ 22 | - (void)getPhotoAlbumOrTakeAPhotoWithController:(UIViewController *)controller photoBlock:(LeePhotoOrAlbumImagePickerBlock)photoBlock withFlag:(NSInteger) showFlag; 23 | 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /ios/Classes/camera/TestViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestViewController.h 3 | // flutter_custom_camera_pugin 4 | // 5 | // Created by androidlongs on 2020/9/12. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface TestViewController : UIViewController 13 | 14 | @end 15 | 16 | NS_ASSUME_NONNULL_END 17 | -------------------------------------------------------------------------------- /ios/Classes/camera/TestViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestViewController.m 3 | // flutter_custom_camera_pugin 4 | // 5 | // Created by androidlongs on 2020/9/12. 6 | // 7 | 8 | #import "TestViewController.h" 9 | #import "LeePhotoOrAlbumImagePicker.h" 10 | 11 | @interface TestViewController () 12 | 13 | @end 14 | 15 | @implementation TestViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | LeePhotoOrAlbumImagePicker *myPicker = [[LeePhotoOrAlbumImagePicker alloc]init]; 20 | [myPicker getPhotoAlbumOrTakeAPhotoWithController:self photoBlock:^(UIImage *image) { 21 | //回掉图片 22 | NSLog(@"回调"); 23 | } withFlag : 3]; 24 | } 25 | 26 | /* 27 | #pragma mark - Navigation 28 | 29 | // In a storyboard-based application, you will often want to do a little preparation before navigation 30 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 31 | // Get the new view controller using [segue destinationViewController]. 32 | // Pass the selected object to the new view controller. 33 | } 34 | */ 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /ios/flutter_custom_camera_pugin.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. 3 | # Run `pod lib lint flutter_custom_camera_pugin.podspec' to validate before publishing. 4 | # 5 | Pod::Spec.new do |s| 6 | s.name = 'flutter_custom_camera_pugin' 7 | s.version = '0.0.1' 8 | s.summary = 'Flutter 的一个自定义相机 插件' 9 | s.description = <<-DESC 10 | Flutter 的一个自定义相机 插件 11 | DESC 12 | s.homepage = 'http://example.com' 13 | s.license = { :file => '../LICENSE' } 14 | s.author = { 'Your Company' => 'email@example.com' } 15 | s.source = { :path => '.' } 16 | s.source_files = 'Classes/**/*' 17 | s.public_header_files = 'Classes/**/*.h' 18 | s.dependency 'Flutter' 19 | s.platform = :ios, '8.0' 20 | s.resources = 'Classes/**/*.{xib,png}' 21 | 22 | # Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported. 23 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' } 24 | end 25 | -------------------------------------------------------------------------------- /lib/flutter_custom_camera_pugin.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter_custom_camera_pugin/src/bean/camera_config_options.dart'; 3 | import 'package:flutter_custom_camera_pugin/src/bean/camera_result_info.dart'; 4 | import 'package:flutter_custom_camera_pugin/src/common_camera_function.dart'; 5 | 6 | export 'package:flutter_custom_camera_pugin/src/bean/camera_result_info.dart'; 7 | export 'package:flutter_custom_camera_pugin/src/bean/camera_config_options.dart'; 8 | class FlutterCustomCameraPugin { 9 | 10 | ///测试插件连接 11 | static Future testPugin() async{ 12 | final CameraResultInfo result = await CommonCameraFunction.test(); 13 | return result ; 14 | } 15 | 16 | ///打开相机 17 | static Future openCamera({CameraConfigOptions cameraConfigOptions}) async{ 18 | //Flutter 向 Android iOS 中基本的发送消息方式 19 | final CameraResultInfo result = await CommonCameraFunction.openCamera(cameraConfigOptions: cameraConfigOptions); 20 | return result ; 21 | } 22 | 23 | ///打开相册 24 | static Future openPhotoAlbum() async { 25 | final CameraResultInfo result = await CommonCameraFunction.openPhotoAlbum(); 26 | return result ; 27 | } 28 | 29 | ///打开系统相机 30 | static Future openSystemCamera({CameraConfigOptions cameraConfigOptions}) async{ 31 | //Flutter 向 Android iOS 中基本的发送消息方式 32 | final CameraResultInfo result = await CommonCameraFunction.openSystemCamera(cameraConfigOptions: cameraConfigOptions); 33 | return result ; 34 | } 35 | 36 | ///打开系统相册 37 | static Future openSystemPhotoAlbum({CameraConfigOptions cameraConfigOptions}) async{ 38 | //Flutter 向 Android iOS 中基本的发送消息方式 39 | final CameraResultInfo result = await CommonCameraFunction.openSystemPhotoAlbum(cameraConfigOptions: cameraConfigOptions); 40 | return result ; 41 | } 42 | ///打开系统相机相册弹框 43 | static Future openSystemAlert({CameraConfigOptions cameraConfigOptions}) async{ 44 | //Flutter 向 Android iOS 中基本的发送消息方式 45 | final CameraResultInfo result = await CommonCameraFunction.openSystemAlert(cameraConfigOptions: cameraConfigOptions); 46 | return result ; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/src/bean/camera_config_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | /// 创建人: Created by zhaolong 5 | /// 创建时间:Created by on 2020/9/9. 6 | /// 7 | /// 可关注公众号:我的大前端生涯 获取最新技术分享 8 | /// 可关注网易云课堂:https://study.163.com/instructor/1021406098.htm 9 | /// 可关注博客:https://blog.csdn.net/zl18603543572 10 | /// 11 | /// 12 | /// 相册配置使用参数 13 | class CameraConfigOptions { 14 | 15 | ///0.0.1 版本 16 | ///默认自定义相册是否显示 相册切换 17 | bool isShowPhotoAlbum = true; 18 | 19 | ///默认自定义相册是否显示 前后镜头切换 20 | bool isShowSelectCamera = true; 21 | 22 | ///默认自定义相册是否显示 闪光灯开关按钮 23 | bool isShowFlashButtonCamera = true; 24 | 25 | /// 是否预览照片 如拍照完成 或者相册选择完成 26 | bool isPreviewImage = true; 27 | 28 | /// 是否启动裁剪功能 如拍照完成 或者相册选择完成 29 | bool isCropImage = false; 30 | 31 | List iconsList =[ 32 | "icons/camera_record_icon.png", 33 | "icons/camera_flash_open_icon.png", 34 | "icons/camera_record_finish.png", 35 | "icons/camera_record_icon.png", 36 | "icons/camera_select_photo_icon.png", 37 | "icons/camera_white_back_icon.png" 38 | ]; 39 | } -------------------------------------------------------------------------------- /lib/src/bean/camera_result_info.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | /// 创建人: Created by zhaolong 5 | /// 创建时间:Created by on 2020/9/9. 6 | /// 7 | /// 可关注公众号:我的大前端生涯 获取最新技术分享 8 | /// 可关注网易云课堂:https://study.163.com/instructor/1021406098.htm 9 | /// 可关注博客:https://blog.csdn.net/zl18603543572 10 | class CameraResultInfo { 11 | 12 | int code; 13 | ///回调的消息 14 | String message =''; 15 | ///回调的数据 16 | dynamic data ; 17 | ///回调的方法名 18 | String method =''; 19 | 20 | static CameraResultInfo fromMap(Map map){ 21 | CameraResultInfo info = new CameraResultInfo(); 22 | info.code= map["code"]; 23 | info.message=map['message']; 24 | info.data=map['data']; 25 | return info; 26 | } 27 | 28 | static CameraResultInfo fromError({int errCode=500,String messag="插件错误"}){ 29 | CameraResultInfo info = new CameraResultInfo(); 30 | info.code= errCode; 31 | info.message=messag; 32 | return info; 33 | } 34 | 35 | @override 36 | String toString() { 37 | return 'CameraResultInfo{code: $code, message: $message}'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/common_camera_function.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | 3 | import '../flutter_custom_camera_pugin.dart'; 4 | import 'bean/camera_result_info.dart'; 5 | 6 | /// 创建人: Created by zhaolong 7 | /// 创建时间:Created by on 2020/9/9. 8 | /// 9 | /// 可关注公众号:我的大前端生涯 获取最新技术分享 10 | /// 可关注网易云课堂:https://study.163.com/instructor/1021406098.htm 11 | /// 可关注博客:https://blog.csdn.net/zl18603543572 12 | class CommonCameraFunction { 13 | //https://blog.csdn.net/zl18603543572/article/details/96043692 14 | String recive = ""; 15 | 16 | //创建 BasicMessageChannel 17 | // flutter_and_native_100 为通信标识 18 | // StandardMessageCodec() 为参数传递的 编码方式 19 | static const messageChannel = const BasicMessageChannel( 20 | 'flutter_and_native_custom_100', StandardMessageCodec()); 21 | 22 | //发送消息 23 | static Future> sendMessage(Map arguments) async { 24 | ///返回的是 Map 类型 25 | Map reply = await messageChannel.send(arguments); 26 | //解析 原生发给 Flutter 的参数 27 | int code = reply["code"]; 28 | String message = reply["message"]; 29 | Map map = Map.from(reply); 30 | print("返回数据 "+reply.toString()); 31 | return Future.value(map); 32 | } 33 | 34 | static Future test() async { 35 | final Map result = await sendMessage( 36 | {"method": "test", "ontent": "测试一下插件连接", "code": 400}); 37 | return CameraResultInfo.fromMap(result); 38 | } 39 | 40 | ///打开相机 41 | static Future openCamera( 42 | {CameraConfigOptions cameraConfigOptions}) async { 43 | Map options = getCameraConfigOptions(cameraConfigOptions); 44 | //Flutter 向 Android iOS 中基本的发送消息方式 45 | final Map result = await sendMessage({ 46 | "method": "openCamera", 47 | "ontent": "打开自定义相机", 48 | "code": 100, 49 | "options": options 50 | }); 51 | return CameraResultInfo.fromMap(result); 52 | } 53 | 54 | static Map getCameraConfigOptions( 55 | CameraConfigOptions cameraConfigOptions) { 56 | if (cameraConfigOptions == null) { 57 | cameraConfigOptions = new CameraConfigOptions(); 58 | } 59 | Map options = new Map(); 60 | options['isShowFlashButtonCamera'] = 61 | cameraConfigOptions.isShowFlashButtonCamera; 62 | options['isShowPhotoAlbum'] = cameraConfigOptions.isShowPhotoAlbum; 63 | options['isShowSelectCamera'] = cameraConfigOptions.isShowSelectCamera; 64 | 65 | options['isPreviewImage'] = cameraConfigOptions.isPreviewImage; 66 | options['isCropImage'] = cameraConfigOptions.isCropImage; 67 | options['iconsList'] = cameraConfigOptions.iconsList; 68 | return options; 69 | } 70 | 71 | ///打开相册 72 | static Future openPhotoAlbum( 73 | {CameraConfigOptions cameraConfigOptions}) async { 74 | Map options = getCameraConfigOptions(cameraConfigOptions); 75 | final Map result = await sendMessage({ 76 | "method": "openPhotoAlbum", 77 | "ontent": "打开系统相册", 78 | "code": 102, 79 | "options": options 80 | }); 81 | 82 | return CameraResultInfo.fromMap(result); 83 | } 84 | 85 | static openSystemCamera({CameraConfigOptions cameraConfigOptions}) async{ 86 | Map options = getCameraConfigOptions(cameraConfigOptions); 87 | final Map result = await sendMessage({ 88 | "method": "openSystemCamera", 89 | "ontent": "打开系统相机", 90 | "code": 102, 91 | "options": options 92 | }); 93 | 94 | return CameraResultInfo.fromMap(result); 95 | } 96 | 97 | static openSystemPhotoAlbum({CameraConfigOptions cameraConfigOptions}) async{ 98 | Map options = getCameraConfigOptions(cameraConfigOptions); 99 | final Map result = await sendMessage({ 100 | "method": "openPhotoAlbum", 101 | "ontent": "打开系统相册", 102 | "code": 102, 103 | "options": options 104 | }); 105 | 106 | return CameraResultInfo.fromMap(result);} 107 | 108 | static openSystemAlert({CameraConfigOptions cameraConfigOptions}) async{ 109 | Map options = getCameraConfigOptions(cameraConfigOptions); 110 | final Map result = await sendMessage({ 111 | "method": "openSystemAlert", 112 | "ontent": "系统弹框选择相机相册", 113 | "code": 102, 114 | "options": options 115 | }); 116 | 117 | return CameraResultInfo.fromMap(result);} 118 | } 119 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.flutter-io.cn" 9 | source: hosted 10 | version: "2.4.1" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.flutter-io.cn" 16 | source: hosted 17 | version: "2.0.0" 18 | charcode: 19 | dependency: transitive 20 | description: 21 | name: charcode 22 | url: "https://pub.flutter-io.cn" 23 | source: hosted 24 | version: "1.1.3" 25 | clock: 26 | dependency: transitive 27 | description: 28 | name: clock 29 | url: "https://pub.flutter-io.cn" 30 | source: hosted 31 | version: "1.0.1" 32 | collection: 33 | dependency: transitive 34 | description: 35 | name: collection 36 | url: "https://pub.flutter-io.cn" 37 | source: hosted 38 | version: "1.14.12" 39 | fake_async: 40 | dependency: transitive 41 | description: 42 | name: fake_async 43 | url: "https://pub.flutter-io.cn" 44 | source: hosted 45 | version: "1.1.0" 46 | flutter: 47 | dependency: "direct main" 48 | description: flutter 49 | source: sdk 50 | version: "0.0.0" 51 | flutter_test: 52 | dependency: "direct dev" 53 | description: flutter 54 | source: sdk 55 | version: "0.0.0" 56 | matcher: 57 | dependency: transitive 58 | description: 59 | name: matcher 60 | url: "https://pub.flutter-io.cn" 61 | source: hosted 62 | version: "0.12.6" 63 | meta: 64 | dependency: transitive 65 | description: 66 | name: meta 67 | url: "https://pub.flutter-io.cn" 68 | source: hosted 69 | version: "1.1.8" 70 | path: 71 | dependency: transitive 72 | description: 73 | name: path 74 | url: "https://pub.flutter-io.cn" 75 | source: hosted 76 | version: "1.7.0" 77 | sky_engine: 78 | dependency: transitive 79 | description: flutter 80 | source: sdk 81 | version: "0.0.99" 82 | source_span: 83 | dependency: transitive 84 | description: 85 | name: source_span 86 | url: "https://pub.flutter-io.cn" 87 | source: hosted 88 | version: "1.7.0" 89 | stack_trace: 90 | dependency: transitive 91 | description: 92 | name: stack_trace 93 | url: "https://pub.flutter-io.cn" 94 | source: hosted 95 | version: "1.9.3" 96 | stream_channel: 97 | dependency: transitive 98 | description: 99 | name: stream_channel 100 | url: "https://pub.flutter-io.cn" 101 | source: hosted 102 | version: "2.0.0" 103 | string_scanner: 104 | dependency: transitive 105 | description: 106 | name: string_scanner 107 | url: "https://pub.flutter-io.cn" 108 | source: hosted 109 | version: "1.0.5" 110 | term_glyph: 111 | dependency: transitive 112 | description: 113 | name: term_glyph 114 | url: "https://pub.flutter-io.cn" 115 | source: hosted 116 | version: "1.1.0" 117 | test_api: 118 | dependency: transitive 119 | description: 120 | name: test_api 121 | url: "https://pub.flutter-io.cn" 122 | source: hosted 123 | version: "0.2.15" 124 | typed_data: 125 | dependency: transitive 126 | description: 127 | name: typed_data 128 | url: "https://pub.flutter-io.cn" 129 | source: hosted 130 | version: "1.1.6" 131 | vector_math: 132 | dependency: transitive 133 | description: 134 | name: vector_math 135 | url: "https://pub.flutter-io.cn" 136 | source: hosted 137 | version: "2.0.8" 138 | sdks: 139 | dart: ">=2.7.0 <3.0.0" 140 | flutter: ">=1.10.0" 141 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_custom_camera_pugin 2 | description: Flutter 的一个自定义相机 插件, Flutter自定义相机,Flutter打开系统相册 3 | version: 0.0.5 4 | homepage: https://github.com/zhaolongs/FlutterCustomCameraPugin.git 5 | 6 | environment: 7 | sdk: ">=2.7.0 <3.0.0" 8 | flutter: ">=1.10.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | 14 | dev_dependencies: 15 | flutter_test: 16 | sdk: flutter 17 | 18 | # For information on the generic Dart part of this file, see the 19 | # following page: https://dart.dev/tools/pub/pubspec 20 | 21 | # The following section is specific to Flutter. 22 | flutter: 23 | # This section identifies this Flutter project as a plugin project. 24 | # The 'pluginClass' and Android 'package' identifiers should not ordinarily 25 | # be modified. They are used by the tooling to maintain consistency when 26 | # adding or updating assets for this project. 27 | plugin: 28 | platforms: 29 | android: 30 | package: com.studyyoun.camera.flutter_custom_camera_pugin 31 | pluginClass: FlutterCustomCameraPuginPlugin 32 | ios: 33 | pluginClass: FlutterCustomCameraPuginPlugin 34 | 35 | # To add assets to your plugin package, add an assets section, like this: 36 | assets: 37 | - icons/camera_record_icon.png 38 | # - images/a_dot_ham.jpeg 39 | # 40 | # For details regarding assets in packages, see 41 | # https://flutter.dev/assets-and-images/#from-packages 42 | # 43 | # An image asset can refer to one or more resolution-specific "variants", see 44 | # https://flutter.dev/assets-and-images/#resolution-aware. 45 | 46 | # To add custom fonts to your plugin package, add a fonts section here, 47 | # in this "flutter" section. Each entry in this list should have a 48 | # "family" key with the font family name, and a "fonts" key with a 49 | # list giving the asset and other descriptors for the font. For 50 | # example: 51 | # fonts: 52 | # - family: Schyler 53 | # fonts: 54 | # - asset: fonts/Schyler-Regular.ttf 55 | # - asset: fonts/Schyler-Italic.ttf 56 | # style: italic 57 | # - family: Trajan Pro 58 | # fonts: 59 | # - asset: fonts/TrajanPro.ttf 60 | # - asset: fonts/TrajanPro_Bold.ttf 61 | # weight: 700 62 | # 63 | # For details regarding fonts in packages, see 64 | # https://flutter.dev/custom-fonts/#from-packages 65 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaolongs/FlutterCustomCameraPugin/9adf832df675f73e983a202a5b3d0f8c11c37e34/settings.gradle -------------------------------------------------------------------------------- /test/flutter_custom_camera_pugin_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/services.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | import 'package:flutter_custom_camera_pugin/flutter_custom_camera_pugin.dart'; 4 | 5 | void main() { 6 | const MethodChannel channel = MethodChannel('flutter_custom_camera_pugin'); 7 | 8 | TestWidgetsFlutterBinding.ensureInitialized(); 9 | 10 | setUp(() { 11 | channel.setMockMethodCallHandler((MethodCall methodCall) async { 12 | return '42'; 13 | }); 14 | }); 15 | 16 | tearDown(() { 17 | channel.setMockMethodCallHandler(null); 18 | }); 19 | 20 | test('getPlatformVersion', () async { 21 | 22 | }); 23 | } 24 | --------------------------------------------------------------------------------