hnvn / flutter_image_cropper

A Flutter plugin for Android and iOS supports cropping images
969 stars 375 forks source link

Flutter App Image Cropper Issue and Update Notification #465

Closed ashdude1401 closed 4 months ago

ashdude1401 commented 4 months ago

I have implemented an image cropper in my Flutter app, and I'm encountering an issue related to updating my app to the latest Flutter version. Currently, I am using Flutter version 3.16.5. Here are the details:

Flutter 3.16.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 78666c8dc5 (4 weeks ago) • 2023-12-19 16:14:14 -0800
Engine • revision 3f3e560236
Tools • Dart 3.2.3 • DevTools 2.28.4

This my code for calling the crop image -

import 'dart:io';
import 'package:camera/camera.dart';
import 'package:eat_healthy/features/search/presentation/controller/search_screen_controller.dart';
import 'package:eat_healthy/utils/constants/colors.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

import 'package:iconsax/iconsax.dart';

import '../../../../utils/constants/sizes.dart';

class SearchScreen extends StatelessWidget {
  SearchScreen({super.key});

  static const routeName = '/takePictureScreen';

  final controller = SearchScreenController.instance;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: TColors.primaryBackground,
        elevation: 0,
        actions: const [
          // IconButton(
          //   onPressed: () {},
          //   icon: const Icon(Iconsax),
          // ),
        ],
      ),
      backgroundColor: TColors.primaryBackground,
      body: Obx(() => controller.isCameraInitialized
          ? Padding(
              padding: const EdgeInsets.all(TSizes.defaultSpace),
              child: ClipRRect(
                  borderRadius: BorderRadius.circular(20),
                  child: controller.takenPicture.value == null
                      ? takePictureView()
                      : takenPicturePreview()),
            )
          : const Center(child: CircularProgressIndicator())),
    );
  }

  Stack takePictureView() {
    return Stack(
      children: [
        CameraPreview(controller.cameraController.cameraController),
        //Take picture red round button
        Positioned(
          bottom: 20,
          right: Get.width / 2 - Get.width / 7,
          child: GestureDetector(
              onTap: () async {
                await controller.takePicture();
              },
              child: Container(
                height: 60,
                width: 60,
                decoration: const BoxDecoration(
                  color: Colors.red,
                  shape: BoxShape.circle,
                ),
              )),
        ),
      ],
    );
  }

  // taken picture preview
  Stack takenPicturePreview() {
    return Stack(
      children: [
        Image.file(File(controller.takenPicture.value!.path)),
        // tick picture button
        Positioned(
          bottom: 20,
          right: Get.width / 2 - Get.width / 7,
          child: GestureDetector(
            onTap: () async {
              // await controller.takePicture();
            },
            child: Container(
                height: 60,
                width: 60,
                decoration: const BoxDecoration(
                  color: TColors.white,
                  shape: BoxShape.circle,
                ),
                child: const Icon(
                  Iconsax.tick_circle,
                  size: 60,
                  color: TColors.primary,
                )),
          ),
        ),
        //edit icon
        Positioned(
          bottom: 20,
          left: 10,
          child: GestureDetector(
            onTap: () async {
              await controller.cropPicture();
            },
            child: Container(
                height: 60,
                width: 60,
                decoration: const BoxDecoration(
                  color: Colors.transparent,
                  shape: BoxShape.circle,
                ),
                child: const Icon(
                  Iconsax.edit,
                  size: 40,
                  color: TColors.primary,
                )),
          ),
        ),

        // retake picture button
        Positioned(
          bottom: 20,
          right: 10,
          child: GestureDetector(
            onTap: () async {
              await controller.retakePicture();
            },
            child: Container(
                height: 60,
                width: 60,
                decoration: const BoxDecoration(
                  color: Colors.transparent,
                  shape: BoxShape.circle,
                ),
                child: const Icon(
                  Iconsax.recovery_convert,
                  size: 40,
                  color: TColors.primary,
                )),
          ),
        ),
      ],
    );
  }
}

and this is controller code


import 'package:camera/camera.dart';
import 'package:eat_healthy/service/camera_service.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:image_cropper/image_cropper.dart';

class SearchScreenController extends GetxController {
  static SearchScreenController get instance {
    if (Get.isRegistered<SearchScreenController>()) {
      return Get.find<SearchScreenController>();
    } else {
      return Get.put(SearchScreenController());
    }
  }

  final cameraController = TCameraController.instance;

  bool get isCameraInitialized => cameraController.isCameraReady.value;

  final takenPicture = Rx<XFile?>(null);

  Future<void> takePicture() async {
    if (!isCameraInitialized) {
      debugPrint('Error: select a camera first.');
      throw Exception('Error: select a camera first.');
    }
    try {
      final XFile picture =
          await cameraController.cameraController.takePicture();
      takenPicture.value = picture;
    } on CameraException catch (e) {
      debugPrint('Error: ${e.code}\nError Message: ${e.description}');
      throw Exception('Error: ${e.code}\nError Message: ${e.description}');
    }

  }

  Future<void> cropPicture() async {
    if (takenPicture.value == null) {
      debugPrint('Error: no picture taken');
      throw Exception('Error: no picture taken');
    }
    try {
      final imageCropper = ImageCropper();

      final croppedFile = await imageCropper
          .cropImage(sourcePath: takenPicture.value!.path, aspectRatioPresets: [
        CropAspectRatioPreset.square,
        CropAspectRatioPreset.ratio3x2,
        CropAspectRatioPreset.original,
        CropAspectRatioPreset.ratio4x3,
        CropAspectRatioPreset.ratio16x9
      ], uiSettings: [
        AndroidUiSettings(
          toolbarTitle: 'Crop Image',
          toolbarColor: Colors.deepOrange,
          toolbarWidgetColor: Colors.white,
          initAspectRatio: CropAspectRatioPreset.original,
          lockAspectRatio: false,
        ),

      ]);

      if (croppedFile != null) {
        takenPicture.value = XFile(croppedFile.path);
      }
    } catch (e) {
      debugPrint('Error: ${e.toString()}');
      rethrow;
    }
  }

  Future<void> retakePicture() async {
    if (takenPicture.value == null) {
      debugPrint('Error: no picture taken');
      throw Exception('Error: no picture taken');
    }
    try {
      takenPicture.value = null;
    } catch (e) {
      debugPrint('Error: ${e.toString()}');
      rethrow;
    }
  }
}
`
and this image controller 
`import 'package:get/get.dart';
import 'package:camera/camera.dart';

class TCameraController extends GetxController {
  static TCameraController get instance {
    if (Get.isRegistered<TCameraController>()) {
      return Get.find<TCameraController>();
    } else {
      return Get.put(TCameraController());
    }
  }

  late CameraController cameraController;
  late List<CameraDescription> cameras;
  late CameraDescription cameraDescription;
   RxBool isCameraReady=false.obs;
  late int selectedCameraIndex;

  @override
  void onInit(){
    super.onInit();
    _initCamera();
  }

  Future<void> _initCamera() async {
    try {
      cameras = await availableCameras();
      selectedCameraIndex = 0;
      cameraDescription = cameras[selectedCameraIndex];
      cameraController = CameraController(cameraDescription, ResolutionPreset.high);
      await cameraController.initialize();
      isCameraReady.value = true;
    } catch (e) {
      print(e);
    }
  }

  @override
  void onClose() {
    super.onClose();
    cameraController.dispose();
  }
}

.Let me know if you need any more information