Flutter图片裁剪插件image_crop的使用

发布于 1周前 作者 yibo5220 来自 Flutter

Flutter 图片裁剪插件 image_crop 的使用

简介

image_crop 是一个用于在 iOS 和 Android 平台上裁剪图片的 Flutter 插件。

该插件包含一个 Crop 小部件。此小部件仅渲染图片、覆盖层和处理程序以裁剪图片。因此,它可以与其他小部件组合以构建自定义的图片裁剪体验。

该插件通过文件来工作,以避免通过方法通道传递大量数据。文件存储在 iOS 和 Android 的缓存文件夹中。因此,如果需要保存实际裁剪后的图片,请确保将文件复制到其他位置。

所有计算密集型工作都在主线程之外通过 iOS 上的调度队列和 Android 上的缓存线程池完成。

注意:该插件仍在开发中,某些功能尚不可用且测试有限。

安装

pubspec.yaml 文件中添加 image_crop 依赖项:

dependencies:
  image_crop: ^0.3.0

然后运行 flutter pub get 来获取新的依赖项。

使用

创建一个用于加载和编辑图片的小部件:

final cropKey = GlobalKey<CropState>();

Widget _buildCropImage() {
  return Container(
    color: Colors.black,
    padding: const EdgeInsets.all(20.0),
    child: Crop(
      key: cropKey,
      image: Image.file(imageFile),
      aspectRatio: 4.0 / 3.0,
    ),
  );
}

访问裁剪值:

  • scale 是一个因子,用于按比例缩放裁剪时图片的宽度和高度。1.0 表示无需缩放。
  • area 是一个矩形,指示图片上要裁剪的部分的位置。
final crop = cropKey.currentState;
// 或者
// final crop = Crop.of(context);
final scale = crop.scale;
final area = crop.area;

if (area == null) {
  // 无法裁剪,小部件未设置好
  // ...
}

请求权限以访问照片:

final permissionsGranted = await ImageCrop.requestPermissions();

读取图片选项,如宽度和高度。这是不加载实际图像到内存中的高效实现。

final options = await getImageOptions(file: file);
debugPrint('image width: ${options.width}, height: ${options.height}');

如果要将大图像加载到内存中,可以使用采样函数,该函数依赖于本机平台在加载到内存之前按比例缩小图像。例如,将图像重新采样为接近 1024x4096 的尺寸。

final sampleFile = await ImageCrop.sampleImage(
  file: originalFile,
  preferredWidth: 1024,
  preferredHeight: 4096,
);

一旦 Crop 小部件准备就绪,就可以使用本机支持进行图片裁剪和缩放。为了生成更高分辨率的裁剪图像,建议使用带有首选最大宽度和高度的采样图像。放大采样图像的分辨率。裁剪后,图像将具有更高的分辨率。示例如下:

final sampledFile = await ImageCrop.sampleImage(
  file: originalFile,
  preferredWidth: (1024 / crop.scale).round(),
  preferredHeight: (4096 / crop.scale).round(),
);

final croppedFile = await ImageCrop.cropImage(
  file: sampledFile,
  area: crop.area,
);

示例代码

以下是一个完整的示例代码,展示了如何使用 image_crop 插件进行图片裁剪。

import 'dart:io';
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_crop/image_crop.dart';
import 'package:image_picker/image_picker.dart';

void main() {
  SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
    statusBarColor: Colors.transparent,
    statusBarBrightness: Brightness.dark,
    statusBarIconBrightness: Brightness.light,
    systemNavigationBarIconBrightness: Brightness.light,
  ));

  runApp(new MyApp());
}

class MyApp extends StatefulWidget {
  [@override](/user/override)
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final cropKey = GlobalKey<CropState>();
  File _file;
  File _sample;
  File _lastCropped;

  [@override](/user/override)
  void dispose() {
    super.dispose();
    _file?.delete();
    _sample?.delete();
    _lastCropped?.delete();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: SafeArea(
        child: Container(
          color: Colors.black,
          padding: const EdgeInsets.symmetric(vertical: 40.0, horizontal: 20.0),
          child: _sample == null ? _buildOpeningImage() : _buildCroppingImage(),
        ),
      ),
    );
  }

  Widget _buildOpeningImage() {
    return Center(child: _buildOpenImage());
  }

  Widget _buildCroppingImage() {
    return Column(
      children: <Widget>[
        Expanded(
          child: Crop.file(_sample, key: cropKey),
        ),
        Container(
          padding: const EdgeInsets.only(top: 20.0),
          alignment: AlignmentDirectional.center,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              TextButton(
                child: Text(
                  'Crop Image',
                  style: Theme.of(context)
                      .textTheme
                      .button
                      .copyWith(color: Colors.white),
                ),
                onPressed: () => _cropImage(),
              ),
              _buildOpenImage(),
            ],
          ),
        )
      ],
    );
  }

  Widget _buildOpenImage() {
    return TextButton(
      child: Text(
        'Open Image',
        style: Theme.of(context).textTheme.button.copyWith(color: Colors.white),
      ),
      onPressed: () => _openImage(),
    );
  }

  Future<void> _openImage() async {
    final pickedFile = await ImagePicker().getImage(source: ImageSource.gallery);
    final file = File(pickedFile.path);
    final sample = await ImageCrop.sampleImage(
      file: file,
      preferredSize: context.size.longestSide.ceil(),
    );

    _sample?.delete();
    _file?.delete();

    setState(() {
      _sample = sample;
      _file = file;
    });
  }

  Future<void> _cropImage() async {
    final scale = cropKey.currentState.scale;
    final area = cropKey.currentState.area;
    if (area == null) {
      // 无法裁剪,小部件未设置好
      return;
    }

    // 按比例放大以使用尽可能多的像素
    // 这将在裁剪图像时采样更高的分辨率
    final sample = await ImageCrop.sampleImage(
      file: _file,
      preferredSize: (2000 / scale).round(),
    );

    final file = await ImageCrop.cropImage(
      file: sample,
      area: area,
    );

    sample.delete();

    _lastCropped?.delete();
    _lastCropped = file;

    debugPrint('$file');
  }
}

更多关于Flutter图片裁剪插件image_crop的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter图片裁剪插件image_crop的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用image_crop插件进行图片裁剪的详细代码示例。需要注意的是,image_crop插件可能指的是image_cropper插件,这是Flutter社区中比较流行的一个图片裁剪插件。如果你确实是指另一个插件,请确保名称正确,并参考其官方文档。以下示例将基于image_cropper插件进行说明。

首先,确保在你的pubspec.yaml文件中添加image_cropper依赖:

dependencies:
  flutter:
    sdk: flutter
  image_cropper: ^x.x.x  # 请替换为最新版本号

然后,运行flutter pub get来安装依赖。

接下来,我们编写代码来实现图片裁剪功能。以下是一个完整的示例,包括选择图片、裁剪图片以及显示裁剪后的图片。

import 'package:flutter/material.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Image Cropper Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ImageCropperScreen(),
    );
  }
}

class ImageCropperScreen extends StatefulWidget {
  @override
  _ImageCropperScreenState createState() => _ImageCropperScreenState();
}

class _ImageCropperScreenState extends State<ImageCropperScreen> {
  File? _imageFile;
  CroppedImage? _croppedImage;

  final ImagePicker _picker = ImagePicker();

  Future<void> _pickImage() async {
    final pickedFile = await _picker.pickImage(source: ImageSource.gallery);

    if (pickedFile != null) {
      File? croppedFile = await ImageCropper().cropImage(
        sourcePath: pickedFile.path,
        aspectRatioPresets: [
          CropAspectRatioPreset.square,
          CropAspectRatioPreset.ratio3x2,
          CropAspectRatioPreset.original,
          CropAspectRatioPreset.ratio4x3,
          CropAspectRatioPreset.ratio16x9
        ],
        androidUiSettings: AndroidUiSettings(
          toolbarTitle: 'Cropper',
          toolbarColor: Colors.deepOrange,
          toolbarWidgetColor: Colors.white,
          initAspectRatio: CropAspectRatioPreset.original,
          lockAspectRatio: false,
        ),
        iosUiSettings: IOSUiSettings(
          minimumAspectRatio: 1.0,
        ),
      );

      if (croppedFile != null) {
        setState(() {
          _croppedImage = CroppedImage.fromFile(croppedFile);
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Image Cropper Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            _imageFile != null
                ? Image.file(
                    _imageFile!,
                    fit: BoxFit.cover,
                    width: 300,
                    height: 300,
                  )
                : Container(),
            _croppedImage != null
                ? Image.file(
                    File(_croppedImage!.path),
                    fit: BoxFit.cover,
                    width: 300,
                    height: 300,
                  )
                : Container(),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _pickImage,
              child: Text('Pick and Crop Image'),
            ),
          ],
        ),
      ),
    );
  }
}

在这个示例中,我们做了以下几件事:

  1. 使用ImagePicker从设备的图库中选择图片。
  2. 使用ImageCropper裁剪选择的图片。
  3. 显示原始图片和裁剪后的图片。

注意:

  • 在实际项目中,你可能需要处理更多的错误和边缘情况。
  • 裁剪后的图片会存储在设备的临时目录中,你可以根据需要将其保存到永久存储位置。
  • 请确保在AndroidManifest.xmlInfo.plist中添加必要的权限,以便访问设备的图库和存储。

希望这个示例能帮助你理解如何在Flutter项目中使用image_cropper插件进行图片裁剪。

回到顶部