Crop Picture (Only for IDE's, cause Flutter flow cant do it)

[image.png] Hi Guys,  i made a Custom Widget to Crop Pictures.  Be aware u can only use it when u work with VS-Codes, because we are unable to access:

 '../../backend/firebase_storage/storage.dart'; 
 '../../auth/auth_util.dart';  

and Android Manifest in Flutter flow. Maybe u can fix this ?

What u have to do for this Widget: Create a Local state: [image.png]Misspelled—so write: croppedPictrueURl Then create a Custom Widget: [image.png]and use this code: import 'dart:io'; import '../../auth/auth_util.dart'; import '../../backend/firebase_storage/storage.dart'; import 'package:flutter/services.dart'; import 'package:image_cropper/image_cropper.dart'; import 'package:image_picker/image_picker.dart'; class SetPhotoScreen extends StatefulWidget { const SetPhotoScreen({ Key? key, this.width, this.height, required this.action, }) : super(key: key); static const id = 'set_photo_screen'; final double? width; final double? height; final Future Function() action; @override State createState() => _SetPhotoScreenState(); } class _SetPhotoScreenState extends State { File? _image; String uploadedFileUrl = ''; var timestamp = DateTime.now().microsecondsSinceEpoch; var downloadUrls = []; var selectedMedia = []; Future _pickImage(ImageSource source) async { try { final image = await ImagePicker().pickImage(source: source); if (image == null) return; File? img = File(image.path); img = await _cropImage(imageFile: img); setState(() { _image = img; selectedMedia.add(img!.path); Navigator.of(context).pop(); }); } on PlatformException catch (e) { print(e); Navigator.of(context).pop(); } } Future _cropImage({required File imageFile}) async { CroppedFile? croppedImage = await ImageCropper().cropImage(sourcePath: imageFile.path); if (croppedImage == null) return null; return File(croppedImage.path); } void _showSelectPhotoOptions(BuildContext context) { showModalBottomSheet( context: context, isScrollControlled: true, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical( top: Radius.circular(25.0), ), ), builder: (context) => DraggableScrollableSheet( initialChildSize: 0.28, maxChildSize: 0.4, minChildSize: 0.28, expand: false, builder: (context, scrollController) { return SingleChildScrollView( controller: scrollController, child: SelectPhotoOptionsScreen( onTap: _pickImage, ), ); }), ); } @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Container( decoration: BoxDecoration( color: Color.fromRGBO(237, 142, 0, 1), border: Border.all( color: Color.fromRGBO(237, 142, 0, 1), width: 0, )), child: Column( children: [ GestureDetector( behavior: HitTestBehavior.translucent, onTap: () { _showSelectPhotoOptions(context); }, child: Center( child: Container( height: 200.0, width: 200.0, color: Color.fromRGBO(237, 142, 0, 1), child: Center( child: _image == null ? const Text( 'No image selected', style: TextStyle(fontSize: 20), ) : CircleAvatar( backgroundImage: FileImage(_image!), radius: 200.0, ), ), ), ), ), Visibility( visible: (_image != null), child: ElevatedButton( onPressed: () async { // ignore: await_only_futures downloadUrls = (await Future.wait( selectedMedia.map( (m) async => await uploadData( "users/$currentUserUid/uploads/signature_$timestamp.png", _image!.readAsBytesSync()), ), )) .where((u) => u != null) .map((u) => u!) .toList(); if (downloadUrls.length == 1) { setState(() => uploadedFileUrl = downloadUrls.first); } print(uploadedFileUrl); FFAppState().croppedPictrueURl = uploadedFileUrl; widget.action.call(); }, style: ElevatedButton.styleFrom( elevation: 10, primary: Colors.grey.shade200, shape: const StadiumBorder(), ), child: Padding( padding: const EdgeInsets.symmetric( vertical: 16, horizontal: 6, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, // crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const SizedBox( width: 14, ), Text( "Upload", style: const TextStyle( fontSize: 18, color: Colors.black, ), ) ], ), ), ), ), ], ), )), ); } } class SelectPhotoOptionsScreen extends StatelessWidget { final Function(ImageSource source) onTap; const SelectPhotoOptionsScreen({ Key? key, required this.onTap, }) : super(key: key); @override Widget build(BuildContext context) { return Container( color: Color.fromARGB(255, 48, 138, 12), padding: const EdgeInsets.all(20), child: Stack( alignment: AlignmentDirectional.topCenter, clipBehavior: Clip.none, children: [ Positioned( top: -35, child: Container( width: 50, height: 6, margin: const EdgeInsets.only(bottom: 20), decoration: BoxDecoration( borderRadius: BorderRadius.circular(2.5), color: Color.fromARGB(255, 170, 32, 32), ), ), ), const SizedBox( height: 20, ), Column(children: [ SelectPhoto( onTap: () => onTap(ImageSource.gallery), icon: Icons.image, textLabel: 'Browse Gallery', ), const SizedBox( height: 10, ), const Center( child: Text( 'OR', style: TextStyle(fontSize: 18), ), ), const SizedBox( height: 10, ), SelectPhoto( onTap: () => onTap(ImageSource.camera), icon: Icons.camera_alt_outlined, textLabel: 'Use a Camera', ), ]) ], ), ); } } class SelectPhoto extends StatelessWidget { final String textLabel; final IconData icon; final void Function()? onTap; const SelectPhoto({ Key? key, required this.textLabel, required this.icon, required this.onTap, }) : super(key: key); @override Widget build(BuildContext context) { return ElevatedButton( onPressed: onTap, style: ElevatedButton.styleFrom( elevation: 10, primary: Colors.grey.shade200, shape: const StadiumBorder(), ), child: Padding( padding: const EdgeInsets.symmetric( vertical: 16, horizontal: 6, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, // crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Icon( icon, color: Colors.black, ), const SizedBox( width: 14, ), Text( textLabel, style: const TextStyle( fontSize: 18, color: Colors.black, ), ) ], ), ), ); } } Download the Code and add this to your AndroidManifest.xml: Then you can use your local state to update a Database of your choice. Hope this helps you.  Still cant understand, why Flutter Flow doesnt have this function!
1
1 reply