Обрезка изображения не работает в GetxController

Ниже приведен код, который я пытался реализовать. Будущий метод pickImage, я думаю, проблема именно в нем. Я расширяю класс с помощью GetxController. Ожидается, что метод выберет и обрежет выбранное изображение с помощью обрезки изображения, а затем установит обрезанное изображение в переменную imageFile, если обрезка прошла успешно.

      import 'dart:io';

import 'package:pamoja/app/data/const.dart';
import 'package:pamoja/app/data/firebase/firebase_functions.dart';
import 'package:pamoja/app/data/global_widgets/indicator.dart';
import 'package:pamoja/app/models/advert_model.dart';
import 'package:pamoja/app/modules/my_adverts/controllers/my_adverts_controller.dart';
import 'package:pamoja/app/routes/app_pages.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
import 'package:image_cropper/image_cropper.dart';

class UploadBlogController extends GetxController {
  TextEditingController title = TextEditingController();
  TextEditingController description = TextEditingController();
  TextEditingController location = TextEditingController();
  TextEditingController category = TextEditingController();
  TextEditingController price = TextEditingController();
  TextEditingController phone = TextEditingController();
  final FirebaseFunctions _functions = FirebaseFunctions();
  File? imageFile;

  Future<void> pickImage() async {
    try {
      ImagePicker _picker = ImagePicker();

      await _picker.pickImage(source: ImageSource.gallery).then((value) async {
        if (value != null) {
          File? croppedFile = await ImageCropper().cropImage(
            sourcePath: value.path,
            aspectRatio: CropAspectRatio(ratioX: 1, ratioY: 1),
            compressQuality: 100,
            maxWidth: 700,
            maxHeight: 700,
            // saveCircleCroppedImage: true,
          );

          if (croppedFile != null) {
            imageFile = croppedFile;
            update();
          }
        }
      });
    } catch (e) {
      showAlert("$e");
    }
  }

  void createBlog() async {
    if (title.text.isNotEmpty && description.text.isNotEmpty) {
      if (imageFile != null && imageFile != "") {
        Indicator.showLoading();

        await _functions
            .uploadBlog(
          title.text,
          description.text,
          imageFile!,
          price.text,
          category.text,
          location.text,
          phone.text,
        )
            .then((value) {
          Indicator.closeLoading();
          showAlert("Your advert created sucessfully");
          // Get.back();
          Get.toNamed(Routes.HOME);
        });
      } else {
        showAlert("Image is required");
      }
    } else {
      showAlert("All fields are required");
    }
  }

  void editBlog(BlogsModel model) async {
    Indicator.showLoading();

    if (title.text.isNotEmpty && description.text.isNotEmpty) {
      if (imageFile == null) {
        Map<String, dynamic> map = {
          'title': title.text,
          'description': description.text,
        };

        await _functions.editBlog(model.id, map).then((value) {
          Get.toNamed(Routes.HOME);
          showAlert("Your ads Updated Sucessfully");
        });
      } else {
        String imageUrl = await _functions.uploadImage(imageFile!);

        Map<String, dynamic> map = {
          'title': title.text,
          'description': description.text,
          'img': imageUrl,
        };

        await _functions.editBlog(model.id, map).then((value) {
          Get.toNamed(Routes.HOME);
          showAlert("Your Advert Updated Sucessfully");
        });
      }
    } else {
      showAlert("All fields are required");
    }

    Indicator.closeLoading();
    updateData();
  }

  void updateData() {
    Get.back();
    Get.toNamed(Routes.HOME);
    if (Get.isRegistered<MyBlogsController>()) {
      final controller = Get.find<MyBlogsController>();

      controller.myBlogs = [];
      Indicator.showLoading();
      controller.getMyBlogData();
    }
  }
}

2 ответа

это я создалreusable single-toneкод для всего моего приложения, чтобы выбрать медиаimageилиvideo. вы можете попробовать или изменить в соответствии с вашими требованиями.

      // Dart imports:
import 'dart:io';

// Package imports:
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';

// Project imports:
import 'package:app/utils/export_utils.dart';

class MediaPicker {
  MediaPicker._();

  static const supportedImageFormates = [".jpeg", ".png"];
  static const supportedVedioFormates = [".mp4"];
  static final picker = ImagePicker();

  // Single image / video selection
  static Future<File?> pickMedia({
    required ImageSource source,
    bool isVideo = false,
    bool isEditing = false,
  }) async {
    try {
      final pickMedia = !isVideo
          ? await picker.pickImage(source: source)
          : await picker.pickVideo(source: source);

      if (pickMedia != null) {
        return isEditing
            ? await editImage(file: File(pickMedia.path))
            : File(pickMedia.path);
      } else {
        return null;
      }
    } catch (ex) {
      "Pick Media error: $ex".printLog();
      return null;
    }
  }

  static Future<File> editImage({required File file}) async {
    final CroppedFile? croppedFile = await ImageCropper().cropImage(
      sourcePath: file.path,
      uiSettings: [
        AndroidUiSettings(
          toolbarTitle: 'Cropper',
          toolbarColor: ColorConst.themePrimaryColor,
          toolbarWidgetColor: ColorConst.white,
          initAspectRatio: CropAspectRatioPreset.original,
          lockAspectRatio: false,
        ),
        IOSUiSettings(
          title: 'Cropper',
        ),
      ],
    );

    if (croppedFile != null) {
      return File(croppedFile.path);
    } else {
      return file;
    }
  }
}

Использование метода добавления вызова при нажатии кнопки с помощьюFuture&asyncметод

      Future<void> btnPickImageTap() async {
    final File? selectImageFile = await MediaPicker.pickMedia(
      source: ImageSource.gallery, 
      isEditing: true, // Default false
    );
}

      source: ImageSource.camera - to pick image from camera. 
isEditing: false - avoid image cropping functionality.
isVideo: to pick video from gallery / camera.

Убедитесь, что для обеих платформ добавлено следующее разрешение

Andriod- AndroidManifest.xml

          <uses-permission android:name="android.permission.CAMERA"/> //Camera
   <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> // Read Storage 

iOSБегун/info.plist

      <key>NSCameraUsageDescription</key>
    <string>App require camera permission to update profile pic</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>App require gallery permission to update profile pic</string>

Как указано в пакетеimage_cropperдобавьте приведенный ниже код вAndroidManifest.xmlпод<applcaiton>ЯРЛЫК

      <activity
  android:name="com.yalantis.ucrop.UCropActivity"
  android:screenOrientation="portrait"
        android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>

Я изменил его по вашей инструкции, это сработало. Ниже приведен пример модификации

      Future<void> pickImage() async {
try {
  ImagePicker _picker = ImagePicker();

  await _picker.pickImage(source: ImageSource.gallery).then((value) async {
    if (value != null) {
      imageFile = File(value.path);
      showAlert(imageFile.toString());
      editImage(imageFile: imageFile);

      // cropImage(imageFile);
    } else {
      showAlert("No image selected");
    }
  });
} catch (e) {
  showAlert("$e");
}}
Future<void> editImage({required File? imageFile}) async {
final File? croppedFile = await ImageCropper().cropImage(
  sourcePath: imageFile!.path,
  androidUiSettings: AndroidUiSettings(
    toolbarTitle: 'Advert Image',
    toolbarColor: Colors.green.shade400,
    toolbarWidgetColor: Colors.white,
    initAspectRatio: CropAspectRatioPreset.original,
    lockAspectRatio: false,
  ),
  iosUiSettings: IOSUiSettings(
    title: 'Cropper',
  ),
);

if (croppedFile != null) {
  imageFile = File(croppedFile.path);
  update();
} else {
  // update();
}}
Другие вопросы по тегам