当前位置: 首页 > news >正文

东莞seo网站排名优化wordpress导入img文件方法

东莞seo网站排名优化,wordpress导入img文件方法,网站建设的用户体验,韶关市住房和城乡建设局网站flutter开发实战-Camera自定义相机拍照功能实现 一、前言 在项目中使用image_picker插件时候#xff0c;在android设备上使用无法默认设置前置摄像头#xff08;暂时不清楚什么原因#xff09;#xff0c;由于项目默认需要使用前置摄像头#xff0c;所以最终采用自定义…flutter开发实战-Camera自定义相机拍照功能实现 一、前言 在项目中使用image_picker插件时候在android设备上使用无法默认设置前置摄像头暂时不清楚什么原因由于项目默认需要使用前置摄像头所以最终采用自定义相机实现拍照功能。 二、Camera使用前设置 在工程的iOS的info.plist文件中添加相机、麦克风权限描述 keyNSCameraUsageDescription/key stringyour usage description here/string keyNSMicrophoneUsageDescription/key stringyour usage description here/string 在工程的Android的gradle设置minSdkVersion 找到android/app/build.gradle文件 minSdkVersion 21 二、使用插件Camera插件 camera : 适用于iOS、Android和Web的Flutter插件允许访问设备摄像头。 我们需要在工程中引入camera插件 pubspec.yaml中引入插件 # Camera相机拍照等camera: ^0.10.55 处理相机访问权限 在初始化相机控制器时可能会引发权限错误需要处理这些错误。 CameraAccessDenied当用户拒绝相机访问权限时抛出。 CameraAccessDeniedWithoutPrompt仅限iOS。当用户先前拒绝该权限时抛出。iOS不允许再次提示警报对话框。用户必须进入“设置”“隐私”“相机”才能访问相机。 CameraAccessRestricted:仅限iOS。当摄像头访问受到限制且用户无法授予权限家长控制时抛出。 AudioAccessDenied当用户拒绝音频访问权限时抛出。 AudioAccessDeniedWithoutPrompt目前仅限iOS。当用户先前拒绝该权限时抛出。iOS不允许再次提示警报对话框。用户必须转到“设置”“隐私”“麦克风”才能启用音频访问。 AudioAccessRestricted:目前仅限iOS。当音频访问受到限制并且用户无法授予权限家长控制时抛出。 2.1、camera功能设置 当使用camera时我们需要设置一些camera的属性内容比如切换前后摄像头、开启拍照、开启预览、停止预览等。 获取cameras final cameras await availableCameras(); camera中使用CameraController来控制相关功能。 设置缩放级别zoomLevel Futurevoid setZoomLevel(double scale) async {await controller!.setZoomLevel(scale);} 切换闪光灯模式 void onSetFlashModeButtonPressed(FlashMode mode) {setFlashMode(mode).then((_) {if (mounted) {setState(() {});}showInSnackBar(Flash mode set to ${mode.toString().split(.).last});});} 设置曝光模式 void onSetExposureModeButtonPressed(ExposureMode mode) {setExposureMode(mode).then((_) {if (mounted) {setState(() {});}showInSnackBar(Exposure mode set to ${mode.toString().split(.).last});});} 设置焦距模式 void onSetFocusModeButtonPressed(FocusMode mode) {setFocusMode(mode).then((_) {if (mounted) {setState(() {});}showInSnackBar(Focus mode set to ${mode.toString().split(.).last});});} 开启预览 Futurevoid onResumePreview() async {final CameraController? cameraController controller;if (cameraController null || !cameraController.value.isInitialized) {print(Error: select a camera first.);return;}if (cameraController.value.isPreviewPaused) {await cameraController.resumePreview();}} 暂停预览 Futurevoid onPausePreview() async {final CameraController? cameraController controller;if (cameraController null || !cameraController.value.isInitialized) {print(Error: select a camera first.);return;}if (!cameraController.value.isPreviewPaused) {await cameraController.pausePreview();}} 切换前后摄像头 void onViewFinderTap(TapDownDetails details, BoxConstraints constraints) {if (controller null) {return;}final CameraController? cameraController controller;final Offset offset Offset(details.localPosition.dx / constraints.maxWidth,details.localPosition.dy / constraints.maxHeight,);cameraController?.setExposurePoint(offset);cameraController?.setFocusPoint(offset);}Futurevoid onNewCameraSelected(CameraDescription cameraDescription) async {final CameraController cameraController CameraController(cameraDescription,ResolutionPreset.high,enableAudio: enableAudio,imageFormatGroup: ImageFormatGroup.jpeg,);controller cameraController;// If the controller is updated then update the UI.cameraController.addListener(() {if (mounted) {setState(() {});}if (cameraController.value.hasError) {print(Camera error ${cameraController.value.errorDescription});}});try {await cameraController.initialize();await Future.wait(FutureObject[// The exposure mode is currently not supported on the web.cameraController.getMaxZoomLevel().then((double value) _maxAvailableZoom value),cameraController.getMinZoomLevel().then((double value) _minAvailableZoom value),]);} on CameraException catch (e) {// _showCameraException(e);}setState(() {isCameraStarting true;});controller!.initialize().then((_) {if (!mounted) {return;}setState(() {isCameraStarting false;});}).catchError((Object e) {if (e is CameraException) {switch (e.code) {case CameraAccessDenied:// Handle access errors here.break;default:// Handle other errors here.break;}}});if (mounted) {setState(() {});}} 上面介绍了一些CameraController的常用设置当然肯定不全大致列了几条。 2.2、WidgetsBinding 生命周期改变相机设置 我们自定义Camera需要在didChangeAppLifecycleState来处理相机。我们需要添加mixin WidgetsBindingObserver 在initState中添加WidgetsBinding.instance?.addObserver(this); 在dispose中移除WidgetsBinding.instance?.removeObserver(this); 这样我们就可以在app的生命周期状态改变时候更新相机 overridevoid didChangeAppLifecycleState(AppLifecycleState state) {final CameraController? cameraController controller;// App state changed before we got the chance to initialize.if (cameraController null || !cameraController.value.isInitialized) {return;}if (state AppLifecycleState.inactive) {cameraController.dispose();} else if (state AppLifecycleState.resumed) {onNewCameraSelected(cameraController.description);}} 2.3、处理预览的画面出现变形的问题 在处理自定义相机功能我们需要处理预览的画面出现变形的问题。这里我们需要使用CameraPreview。 我们需要使用Transform.scale来进行处理处理预览的画面出现变形的问题的解决代码如下 Widget buildCameraPreviewWidget(BuildContext context) {final Size size MediaQuery.of(context).size;final CameraController? cameraController controller;return Container(width: size.width,height: size.height,child: Stack(alignment: Alignment.center,clipBehavior: Clip.hardEdge,children: [RepaintBoundary(key: _cameraViewGlobalKey,child: Transform.scale(scale: 1.0,// scale: controller!.value.aspectRatio / deviceRatio,alignment: Alignment.center,child: AspectRatio(aspectRatio: size.aspectRatio,child: OverflowBox(alignment: Alignment.center,child: FittedBox(fit: BoxFit.fitHeight,child: SizedBox(width: size.width,height: size.width * cameraController!.value.aspectRatio,child: Stack(fit: StackFit.expand, children: Widget[_cameraPreviewWidget(),]),),),),),),),],),);}/// Display the preview from the camera (or a message if the preview is not available).Widget _cameraPreviewWidget() {final CameraController? cameraController controller;if (cameraController null || !cameraController.value.isInitialized) {return const Text(cameraController未初始化完成,style: TextStyle(color: Colors.white,fontSize: 24.0,fontWeight: FontWeight.w900,),);} else {return Listener(onPointerDown: (_) _pointers,onPointerUp: (_) _pointers--,child: CameraPreview(controller!,child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {return GestureDetector(behavior: HitTestBehavior.opaque,onScaleStart: _handleScaleStart,onScaleUpdate: _handleScaleUpdate,onTapDown: (TapDownDetails details) onViewFinderTap(details, constraints),);}),),);}} 在代码中我们使用Transform.scale设置为1.0当设置AspectRatio来设置size.aspectRatio。 2.4、实现拍照功能 在我们代码中我们使用takePicture来实现拍照拍照代码如下 Futurevoid onTakePicture() async {setState(() {isTaking true;});takePicture().then((XFile? file) async {if (mounted) {onPausePreview();if (file ! null) {// 保存到相册// await SaveToAlbumUtil.saveLocalImage(file.path);RenderBox renderBox _cameraContainerGlobalKey.currentContext!.findRenderObject() as RenderBox;// offset.dx , offset.dy 就是控件的左上角坐标Offset offset renderBox.localToGlobal(Offset.zero);//获取sizeSize size renderBox.size;// 创建文件pathString imageDir await PathUtil.createDirectory(local_images);String imagePath $imageDir/${TimeUtil.currentTimeMillis()}.png;// // 获取当前设备的像素比double dpr ui.window.devicePixelRatio;print(devicePixelRatio:${dpr});print(offset:(${offset.dx},${offset.dy})--size:(${size.width},${size.height}));File? targetFile await ImageUtil.cropImage(file.path,imagePath,x: (dpr * offset.dx).floor(),y: (dpr * offset.dy).floor(),width: (dpr * size.width).ceil(),height: (dpr * size.height).ceil(),flipHorizontal: isCameraFront,);print(cropImage targetFile:${targetFile});if (targetFile ! null) {selectedImagePath targetFile.path;// await SaveToAlbumUtil.saveLocalImage(targetFile.path);}setState(() {isHasTakePhoto true;});} else {// 没有获得图片重试}setState(() {isTaking false;});}});} 在裁剪图片中实现如下 import dart:io; import dart:math; import dart:ui as ui; import dart:math as math; import package:flutter/cupertino.dart; import package:flutter/foundation.dart; import package:flutter/rendering.dart; import package:image/image.dart as IMG;class ImageUtil {//拿到图片的字节数组static Futureui.Image loadImageByFile(String path) async {var list await File(path).readAsBytes();return ImageUtil.loadImageByUInt8List(list);}//通过[Uint8List]获取图片static Futureui.Image loadImageByUInt8List(Uint8List list) async {ui.Codec codec await ui.instantiateImageCodec(list);ui.FrameInfo frame await codec.getNextFrame();return frame.image;}// 根据GlobalKey来截图Widgetstatic FutureUint8List? makeImageUInt8List(GlobalKey globalKey) async {RenderRepaintBoundary boundary globalKey.currentContext?.findRenderObject() as RenderRepaintBoundary;// 这个可以获取当前设备的像素比var dpr ui.window.devicePixelRatio;ui.Image image await boundary.toImage(pixelRatio: dpr);ByteData? byteData await image.toByteData(format: ui.ImageByteFormat.png);Uint8List? pngBytes byteData?.buffer.asUint8List();return pngBytes;}static FutureFile? cropSquare(String srcFilePath, String destFilePath, bool flip) async {var bytes await File(srcFilePath).readAsBytes();IMG.Image? src IMG.decodeImage(bytes);if (src ! null) {var cropSize min(src.width, src.height);int offsetX (src.width - min(src.width, src.height)) ~/ 2;int offsetY (src.height - min(src.width, src.height)) ~/ 2;// IMG.Image destImage IMG.copyCrop(src, offsetX, offsetY, cropSize, cropSize);IMG.Image destImage IMG.copyCrop(src,x: offsetX, y: offsetY, width: cropSize, height: cropSize);if (flip) {destImage IMG.flipVertical(destImage);}var jpg IMG.encodeJpg(destImage);return await File(destFilePath).writeAsBytes(jpg);} else {throw StateError(cropSquare error);}}static FutureFile? cropImage(String srcFilePath,String destFilePath, {required int x,required int y,required int width,required int height,bool flipVertical false,bool flipHorizontal false,}) async {var bytes await File(srcFilePath).readAsBytes();IMG.Image? src IMG.decodeImage(bytes);if (src ! null) {print(cropImage scr size:(${src.width},${src.height}));IMG.Image destImage IMG.copyCrop(src,x: x, y: y, width: width, height: height);if (flipVertical) {destImage IMG.flipVertical(destImage);}if (flipHorizontal) {destImage IMG.flipHorizontal(destImage);}var jpg IMG.encodeJpg(destImage);return await File(destFilePath).writeAsBytes(jpg);} else {throw StateError(cropSquare error);}} } 2.5、拍照完重拍逻辑 当拍照后可能需要重新拍照这时候我们需要重拍逻辑。 void onRetakeButtonPressed() {setState(() {isHasTakePhoto false;});selectedImagePath null;onResumePreview();}Futurevoid onResumePreview() async {final CameraController? cameraController controller;if (cameraController null || !cameraController.value.isInitialized) {print(Error: select a camera first.);return;}if (cameraController.value.isPreviewPaused) {await cameraController.resumePreview();}} 三、实现自定义相机拍照的功能完整代码 我们实现了实现自定义相机拍照的功能完整代码如下 // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file.// ignore_for_file: public_member_api_docsimport dart:async; import dart:io; import package:camera/camera.dart; import package:flutter/foundation.dart; import package:flutter/material.dart; import package:flutter_app_demolab/image_util.dart; import package:flutter_app_demolab/path_util.dart; import dart:ui as ui;import package:flutter_app_demolab/tools/utils/color_util.dart; import package:flutter_app_demolab/tools/utils/time_util.dart; import package:flutter_screenutil/flutter_screenutil.dart;class MyCameraPage extends StatefulWidget {const MyCameraPage({super.key,required this.cameras,required this.onSelectedImagePathPressed,});final ListCameraDescription cameras;final Function(String? selectedImagePath) onSelectedImagePathPressed;overrideStateMyCameraPage createState() _MyCameraPageState(); }class _MyCameraPageState extends StateMyCameraPagewith WidgetsBindingObserver, TickerProviderStateMixin {CameraController? controller;GlobalKey _cameraViewGlobalKey GlobalKey();GlobalKey _cameraContainerGlobalKey GlobalKey();bool enableAudio false;// Counting pointers (number of user fingers on screen)///以下是关于手指缩放画面的变量int _pointers 0;double _minAvailableZoom 1.0;double _maxAvailableZoom 1.0;double _currentScale 1.0;double _baseScale 1.0;Size? mediaSize;double? scale;double? defaultZoomLevel;bool isHasTakePhoto false;bool isCameraFront true;String? selectedImagePath;bool isTaking false;bool isCameraStarting false;overridevoid initState() {super.initState();// To display the current output from the Camera,// create a CameraController.if (widget.cameras.isNotEmpty widget.cameras.length 2) {controller CameraController(// Get a specific camera from the list of available cameras.widget.cameras[1],// Define the resolution to use.ResolutionPreset.high,);// Next, initialize the controller. This returns a Future.setState(() {isCameraStarting true;});controller!.initialize().then((_) {if (!mounted) {return;}setState(() {isCameraStarting false;});}).catchError((Object e) {if (e is CameraException) {switch (e.code) {case CameraAccessDenied:// Handle access errors here.break;default:// Handle other errors here.break;}}});}WidgetsBinding.instance?.addObserver(this);}overridevoid dispose() {WidgetsBinding.instance?.removeObserver(this);controller?.dispose();super.dispose();}overridevoid didChangeAppLifecycleState(AppLifecycleState state) {final CameraController? cameraController controller;// App state changed before we got the chance to initialize.if (cameraController null || !cameraController.value.isInitialized) {return;}if (state AppLifecycleState.inactive) {cameraController.dispose();} else if (state AppLifecycleState.resumed) {onNewCameraSelected(cameraController.description);}}final GlobalKeyScaffoldState _scaffoldKey GlobalKeyScaffoldState();overrideWidget build(BuildContext context) {return Scaffold(key: _scaffoldKey,body: buildCameraContainer(context),);}Widget buildCameraContainer(BuildContext context) {final Size size MediaQuery.of(context).size;if (widget.cameras.isEmpty) {return Container(width: size.width,height: size.height,decoration: const BoxDecoration(color: Colors.black,),child: Text(未获取到可用的相机请退出重试。,textAlign: TextAlign.center,maxLines: 2,overflow: TextOverflow.ellipsis,softWrap: true,style: TextStyle(fontSize: 16,fontWeight: FontWeight.w500,fontStyle: FontStyle.normal,color: ColorUtil.hexColor(0xffffff),decoration: TextDecoration.none,),),);} else {return Container(key: _cameraContainerGlobalKey,width: size.width,height: size.height,decoration: const BoxDecoration(color: Colors.black,),child: Stack(alignment: Alignment.center,children: [Column(children: [Expanded(child: buildFutureBuilder(context),)],),buildStackBarWidget(context),],),);}}Widget buildFutureBuilder(BuildContext context) {if (controller ! null controller!.value.isInitialized) {///初始化完成以后再获取可以缩放画面最大最小的参数mediaSize MediaQuery.of(context).size;scale 1 / (controller!.value.aspectRatio * mediaSize!.aspectRatio);controller!.getMaxZoomLevel().then((double value) _maxAvailableZoom value);controller!.getMinZoomLevel().then((double value) _minAvailableZoom value);return buildCameraPreviewWidget(context);}return const Center(child: CircularProgressIndicator());}Widget buildStackBarWidget(BuildContext context) {final Size size MediaQuery.of(context).size;double bottomBarHeight 120;double cameraHeight size.height - bottomBarHeight;EdgeInsets viewPadding MediaQuery.of(context).viewPadding;return Container(child: Stack(children: [Positioned(bottom: 0,child: Container(width: size.width,height: bottomBarHeight,color: Colors.transparent,child: Stack(alignment: Alignment.center,children: [Positioned(left: 25,child: buildCloseIcon(context),),buildTakePhotoButton(context),Positioned(right: 25,child: buildRetakeButton(context),),],),),),Positioned(top: viewPadding.top 25,right: 10,child: buildExchangeButton(context),),],),);}Widget buildCameraPreviewWidget(BuildContext context) {final Size size MediaQuery.of(context).size;final CameraController? cameraController controller;return Container(width: size.width,height: size.height,child: Stack(alignment: Alignment.center,clipBehavior: Clip.hardEdge,children: [RepaintBoundary(key: _cameraViewGlobalKey,child: Transform.scale(scale: 1.0,// scale: controller!.value.aspectRatio / deviceRatio,alignment: Alignment.center,child: AspectRatio(aspectRatio: size.aspectRatio,child: OverflowBox(alignment: Alignment.center,child: FittedBox(fit: BoxFit.fitHeight,child: SizedBox(width: size.width,height: size.width * cameraController!.value.aspectRatio,child: Stack(fit: StackFit.expand, children: Widget[_cameraPreviewWidget(),]),),),),),),),],),);}/// Display the preview from the camera (or a message if the preview is not available).Widget _cameraPreviewWidget() {final CameraController? cameraController controller;if (cameraController null || !cameraController.value.isInitialized) {return const Text(cameraController未初始化完成,style: TextStyle(color: Colors.white,fontSize: 24.0,fontWeight: FontWeight.w900,),);} else {return Listener(onPointerDown: (_) _pointers,onPointerUp: (_) _pointers--,child: CameraPreview(controller!,child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {return GestureDetector(behavior: HitTestBehavior.opaque,onScaleStart: _handleScaleStart,onScaleUpdate: _handleScaleUpdate,onTapDown: (TapDownDetails details) onViewFinderTap(details, constraints),);}),),);}}Widget buildCloseIcon(BuildContext context) {return GestureDetector(onTap: () {Navigator.pop(context);},child: Container(color: Colors.transparent,child: Container(width: 50,height: 50,decoration: BoxDecoration(color: Colors.transparent,border: Border.all(color: Colors.transparent,style: BorderStyle.solid,width: 1,),borderRadius: BorderRadius.all(Radius.circular(20)),),child: Icon(Icons.close,size: 30,color: Colors.white,weight: 0.5,),),),);}Widget buildTakePhotoButton(BuildContext context) {return GestureDetector(onTap: () {if (isTaking false) {if (isHasTakePhoto true) {widget.onSelectedImagePathPressed(selectedImagePath);Navigator.pop(context);} else {onTakePicturePressed();}}},child: Container(color: Colors.transparent,child: Container(width: 60,height: 60,decoration: const BoxDecoration(color: Colors.transparent,),child: Stack(alignment: Alignment.center,children: [Image.asset(assets/camera/my_take_photo.png,width: 60.0,height: 60.0,fit: BoxFit.contain,),buildHasCheck(context),],),),),);}Widget buildHasCheck(BuildContext context) {if (isTaking true) {return buildLoading(context);}if (isHasTakePhoto) {return Icon(Icons.check,size: 30,color: Colors.black,weight: 0.5,);}return Container();}Widget buildExchangeButton(BuildContext context) {if (isHasTakePhoto true) {return Container();}return GestureDetector(onTap: () {onExchangeCameraPressed();},child: Container(color: Colors.transparent,child: Container(width: 50,height: 50,decoration: BoxDecoration(color: Colors.transparent,border: Border.all(color: Colors.transparent,style: BorderStyle.solid,width: 2,),borderRadius: BorderRadius.all(Radius.circular(20)),),child: Container(width: 40,height: 40,decoration: BoxDecoration(color: Colors.transparent,border: Border.all(color: Colors.transparent,style: BorderStyle.solid,width: 5,),borderRadius: BorderRadius.all(Radius.circular(20)),),child: Image.asset(assets/camera/my_exchange_camera.png,width: 50.0,height: 50.0,fit: BoxFit.contain,),),),),);}Widget buildRetakeButton(BuildContext context) {if (isHasTakePhoto false) {return Container();}return GestureDetector(onTap: () {onRetakeButtonPressed();},child: Container(color: Colors.transparent,child: Container(width: 70,height: 38,alignment: Alignment.center,decoration: BoxDecoration(color: ColorUtil.hexColor(0x000000, alpha: 0.25),border: Border.all(color: Colors.transparent,style: BorderStyle.solid,width: 2,),borderRadius: BorderRadius.all(Radius.circular(5)),),child: Text(重拍,textAlign: TextAlign.center,maxLines: 2,overflow: TextOverflow.ellipsis,softWrap: true,style: TextStyle(fontSize: 16,fontWeight: FontWeight.w500,fontStyle: FontStyle.normal,color: ColorUtil.hexColor(0xffffff),decoration: TextDecoration.none,),),),),);}Widget buildLoading(BuildContext context) {return SizedBox(height: 58,width: 58,child: CircularProgressIndicator(backgroundColor: Colors.grey[200],valueColor: AlwaysStoppedAnimation(Colors.blue),),);}void onRetakeButtonPressed() {setState(() {isHasTakePhoto false;});selectedImagePath null;onResumePreview();}Futurevoid onPausePreview() async {final CameraController? cameraController controller;if (cameraController null || !cameraController.value.isInitialized) {print(Error: select a camera first.);return;}if (!cameraController.value.isPreviewPaused) {await cameraController.pausePreview();}}Futurevoid onResumePreview() async {final CameraController? cameraController controller;if (cameraController null || !cameraController.value.isInitialized) {print(Error: select a camera first.);return;}if (cameraController.value.isPreviewPaused) {await cameraController.resumePreview();}}Futurevoid onExchangeCameraPressed() async {setState(() {isHasTakePhoto false;});if (isCameraFront true) {if (widget.cameras.isNotEmpty widget.cameras.length 2) {onNewCameraSelected(widget.cameras[0]);}isCameraFront false;} else {if (widget.cameras.isNotEmpty widget.cameras.length 2) {onNewCameraSelected(widget.cameras[1]);}isCameraFront true;}}void onTakePicturePressed() {onTakePicture();}Futurevoid onTakePicture() async {setState(() {isTaking true;});takePicture().then((XFile? file) async {if (mounted) {onPausePreview();if (file ! null) {// 保存到相册// await SaveToAlbumUtil.saveLocalImage(file.path);RenderBox renderBox _cameraContainerGlobalKey.currentContext!.findRenderObject() as RenderBox;// offset.dx , offset.dy 就是控件的左上角坐标Offset offset renderBox.localToGlobal(Offset.zero);//获取sizeSize size renderBox.size;// 创建文件pathString imageDir await PathUtil.createDirectory(local_images);String imagePath $imageDir/${TimeUtil.currentTimeMillis()}.png;// // 获取当前设备的像素比double dpr ui.window.devicePixelRatio;print(devicePixelRatio:${dpr});print(offset:(${offset.dx},${offset.dy})--size:(${size.width},${size.height}));File? targetFile await ImageUtil.cropImage(file.path,imagePath,x: (dpr * offset.dx).floor(),y: (dpr * offset.dy).floor(),width: (dpr * size.width).ceil(),height: (dpr * size.height).ceil(),flipHorizontal: isCameraFront,);print(cropImage targetFile:${targetFile});if (targetFile ! null) {selectedImagePath targetFile.path;// await SaveToAlbumUtil.saveLocalImage(targetFile.path);}setState(() {isHasTakePhoto true;});} else {// 没有获得图片重试}setState(() {isTaking false;});}});}Futurevoid _handleScaleStart(ScaleStartDetails details) async {_baseScale _currentScale;await controller!.setZoomLevel(_minAvailableZoom);}Futurevoid _handleScaleUpdate(ScaleUpdateDetails details) async {// When there are not exactly two fingers on screen dont scaleif (controller null || _pointers ! 2) {return;}_currentScale (_baseScale * details.scale).clamp(_minAvailableZoom, _maxAvailableZoom);await controller!.setZoomLevel(_currentScale);}void onViewFinderTap(TapDownDetails details, BoxConstraints constraints) {if (controller null) {return;}final CameraController? cameraController controller;final Offset offset Offset(details.localPosition.dx / constraints.maxWidth,details.localPosition.dy / constraints.maxHeight,);cameraController?.setExposurePoint(offset);cameraController?.setFocusPoint(offset);}Futurevoid onNewCameraSelected(CameraDescription cameraDescription) async {final CameraController cameraController CameraController(cameraDescription,ResolutionPreset.high,enableAudio: enableAudio,imageFormatGroup: ImageFormatGroup.jpeg,);controller cameraController;// If the controller is updated then update the UI.cameraController.addListener(() {if (mounted) {setState(() {});}if (cameraController.value.hasError) {print(Camera error ${cameraController.value.errorDescription});}});try {await cameraController.initialize();await Future.wait(FutureObject[// The exposure mode is currently not supported on the web.cameraController.getMaxZoomLevel().then((double value) _maxAvailableZoom value),cameraController.getMinZoomLevel().then((double value) _minAvailableZoom value),]);} on CameraException catch (e) {// _showCameraException(e);}setState(() {isCameraStarting true;});controller!.initialize().then((_) {if (!mounted) {return;}setState(() {isCameraStarting false;});}).catchError((Object e) {if (e is CameraException) {switch (e.code) {case CameraAccessDenied:// Handle access errors here.break;default:// Handle other errors here.break;}}});if (mounted) {setState(() {});}}FutureXFile? takePicture() async {final CameraController? cameraController controller;if (cameraController null || !cameraController.value.isInitialized) {print(Error: select a camera first.);return null;}if (cameraController.value.isTakingPicture) {// A capture is already pending, do nothing.return null;}try {final XFile file await cameraController.takePicture();return file;} on CameraException catch (e) {print(takePicture CameraException e:${e.toString()});return null;}} } 当需要拍照时候我们调用showModalBottomSheet来打开camera //显示底部弹窗static void bottomSheetDialog(BuildContext context, Widget widget) {showModalBottomSheet(context: context,isScrollControlled: true,builder: (ctx) {return widget;},);}//返回上一级static void pop(BuildContext context) {Navigator.pop(context);} 打开自定义相机页面 Futurevoid testCustomCamera(BuildContext context) async {final cameras await availableCameras();DialogUtils.bottomSheetDialog(context,MyCameraPage(cameras: cameras,onSelectedImagePathPressed: (String? selectedImagePath) {print(selectedImageFilePath:${selectedImagePath});if (selectedImagePath ! null) {// File imageFile File(selectedImagePath!);// if (callback ! null) {// callback(imageFile);// }}},),);} https://brucegwo.blog.csdn.net/article/details/135997096 四、小结 flutter开发实战-Camera自定义相机拍照功能实现 学习记录每天不停进步。
http://www.hkea.cn/news/14301008/

相关文章:

  • 山东济南网站新闻a5wordpress模板
  • 网站地图 百度一鸣东莞网站建设公司
  • 建个站的免费网站能上百度吗唐山市住房和城乡建设局官方网站
  • 成都专业建站推广公司wordpress模板商业用
  • 新手怎么做网站推广珠海专业网站建设费用
  • seo百度贴吧漳州优化网站建设
  • 网站设计的优点和缺点大连知名互联网公司
  • 本地网站搭建工具网络营销的定义是什么?
  • 阜宁网站制作选哪家优秀广告案例分析
  • 网站空间ftp内涵网站源码
  • 眉山网站建设公司wordpress 成功案例
  • 静态网站开发外文文献传统类型的企业网站
  • 网站做任务给钱的国美在线网站建设
  • 网站备案丢失免费做图网站有哪些
  • 万载网站建设如何利用网站来提升企业形象
  • 可以看的网站的浏览器有哪些网站建设 营销
  • 柬埔寨网站开发百度网站收录
  • 造作网站开发网站建设有哪些项目
  • 网站前期准备工作信阳市住房和城乡建设厅网站
  • 现在海外做的比较好一点的网站详情页设计理念怎么写
  • 网站建设 无锡哈尔滨小程序制作公司
  • 网站开发技术发展史城乡规划专业招聘信息网
  • 青岛做网站的wordpress qq空间
  • 网站代发外链wordpress 导航 class
  • 装修平台网站有哪些Wordpress禁止爬虫ip
  • 淘宝做网站价格深圳做h5网站
  • 大连网站建设新图闻国家对小微企业扶持2022政策
  • 江门门户网站域名网站网址
  • 企业为何做网站哈尔滨网站建设优化
  • 建设网站视频百度云盘中国免费的企业名录