Flutter图片裁剪插件picture_cropper的使用

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

Flutter图片裁剪插件picture_cropper的使用

简介

picture_cropper 是一个用于Flutter的图片裁剪插件,它支持从相机拍摄照片或从相册选择图片,并提供多种编辑功能。本文将详细介绍如何在Flutter项目中集成和使用该插件。

插件特点

  • 从相机拍摄照片
  • 从相册选择图片
  • 提供多种裁剪模式(如二维码、竖版卡片、横版卡片等)
  • 支持图片的基本编辑功能(旋转、缩放、滤镜等)

安装

首先,在你的 pubspec.yaml 文件中添加 picture_cropper 作为依赖项:

dependencies:
  picture_cropper: ^latest_version

然后导入 Dart 代码:

import 'package:picture_cropper/picture_cropper.dart';

iOS 配置

Info.plist 文件中添加以下权限配置:

<key>NSPhotoLibraryUsageDescription</key>
<string>Used to demonstrate image picker plugin</string>
<key>NSCameraUsageDescription</key>
<string>Used to demonstrate image picker plugin</string>
<key>NSMicrophoneUsageDescription</key>
<string>Used to capture audio for image picker plugin</string>

Android 配置

无需额外配置。

示例代码

下面是一个完整的示例,展示了如何使用 picture_cropper 插件进行图片的选择和裁剪。

主页面示例

import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:picture_cropper/picture_cropper.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light);
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Picture Editor Sample',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      initialRoute: '/',
      routes: {
        '/': (context) => const MyHomePage(),
        '/editor': (context) => const EditorPage(),
      },
      onGenerateRoute: (settings) {
        if (settings.name == '/crop') {
          final image = settings.arguments as ui.Image;
          return MaterialPageRoute(
            builder: (context) {
              return CropImagePage(image: image);
            },
          );
        }
        assert(false, 'Need to implement ${settings.name}');
        return null;
      },
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final pictureCropperController = PictureCropperController(isPicker: true);
  int _cropStatus = 0; // 0 = qr, 1 = vertical card, 2 = card, 3 = clear
  bool _isLoading = false;

  void isLoading(bool value) {
    _isLoading = value;
    setState(() {});
  }

  [@override](/user/override)
  void dispose() {
    pictureCropperController.pictureEditorControllerDispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: SafeArea(
        child: Stack(
          children: [
            Center(
              child: PicturePicker(
                controller: pictureCropperController,
                onSetOriginalImage: () async {
                  final result = await Navigator.pushNamed(context, '/editor');
                  if (result == true) {
                    pictureCropperController.changeCropGuidelineType(
                        pictureCropperController.cropGuidelineType);
                  }
                },
              ),
            ),
            Container(
              padding: const EdgeInsets.all(12),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  InkWell(
                    onTap: () {
                      setState(() {
                        _cropStatus = 0;
                        pictureCropperController
                            .changeCropGuidelineType(CropGuideLineType.qr);
                      });
                    },
                    child: Icon(
                      Icons.crop_din,
                      color: _cropStatus == 0 ? Colors.blue : Colors.white,
                      size: 32,
                    ),
                  ),
                  InkWell(
                    onTap: () {
                      setState(() {
                        _cropStatus = 1;
                        pictureCropperController.changeCropGuidelineType(
                            CropGuideLineType.verticalCard);
                      });
                    },
                    child: Icon(
                      Icons.crop_portrait,
                      color: _cropStatus == 1 ? Colors.blue : Colors.white,
                      size: 32,
                    ),
                  ),
                  InkWell(
                    onTap: () {
                      setState(() {
                        _cropStatus = 2;
                        pictureCropperController
                            .changeCropGuidelineType(CropGuideLineType.card);
                      });
                    },
                    child: Icon(
                      Icons.crop_3_2,
                      color: _cropStatus == 2 ? Colors.blue : Colors.white,
                      size: 32,
                    ),
                  ),
                  InkWell(
                    onTap: () {
                      setState(() {
                        _cropStatus = 3;
                        pictureCropperController
                            .changeCropGuidelineType(CropGuideLineType.clear);
                      });
                    },
                    child: Icon(
                      Icons.not_interested,
                      color: _cropStatus == 3 ? Colors.blue : Colors.white,
                      size: 32,
                    ),
                  ),
                ],
              ),
            ),
            Align(
              alignment: Alignment.bottomCenter,
              child: Container(
                padding: const EdgeInsets.all(24),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    InkWell(
                      onTap: () async {
                        isLoading(true);
                        await pictureCropperController.pickImageFromGallery();
                        isLoading(false);
                      },
                      child: const Icon(
                        Icons.photo,
                        color: Colors.white,
                        size: 32,
                      ),
                    ),
                    InkWell(
                      onTap: () async {
                        isLoading(true);
                        await pictureCropperController.takePicture();
                        isLoading(false);
                      },
                      child: const Icon(
                        Icons.camera,
                        color: Colors.white,
                        size: 64,
                      ),
                    ),
                    InkWell(
                      onTap: pictureCropperController.toggleCameraDirection,
                      child: const Icon(
                        Icons.change_circle,
                        color: Colors.white,
                        size: 32,
                      ),
                    ),
                  ],
                ),
              ),
            ),
            Visibility(
              visible: _isLoading,
              child: Stack(
                children: <Widget>[
                  Opacity(
                    opacity: 0.5,
                    child: Container(
                      color: Colors.black,
                      width: double.infinity,
                      height: double.infinity,
                    ),
                  ),
                  const Padding(
                    padding: EdgeInsets.only(bottom: 16),
                    child: Center(
                      child: CircularProgressIndicator(color: Colors.blue),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

编辑页面示例

import 'package:flutter/material.dart';
import 'package:picture_cropper/picture_cropper.dart';

class EditorPage extends StatelessWidget {
  const EditorPage({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    final pictureCropperController = PictureCropperController();

    return Scaffold(
      body: SafeArea(
        child: PictureEditor(
          controller: pictureCropperController,
          onCropComplete: (image) {
            Navigator.pushNamed(context, '/crop', arguments: image);
          },
        ),
      ),
    );
  }
}

裁剪结果页面示例

import 'dart:ui' as ui;

import 'package:flutter/material.dart';

class CropImagePage extends StatelessWidget {
  final ui.Image image;

  const CropImagePage({required this.image, super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Cropped Image'),
      ),
      body: Center(
        child: Image(image: Image.memory(image.toByteData().buffer.asUint8List()).image),
      ),
    );
  }
}

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

1 回复

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


当然,下面是一个关于如何在Flutter中使用picture_cropper插件进行图片裁剪的示例代码。这个插件允许用户从相机或图库中选取图片,并进行裁剪。

1. 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  picture_cropper: ^2.0.0  # 请检查最新版本号

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

2. 导入插件

在你的Dart文件中导入picture_cropper插件:

import 'package:picture_cropper/picture_cropper.dart';
import 'package:image_picker/image_picker.dart';  // 用于选择图片

3. 配置权限

AndroidManifest.xml中添加必要的权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA"/>

对于iOS,需要在Info.plist中添加权限描述:

<key>NSCameraUsageDescription</key>
<string>Need camera access</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Need photo library access</string>
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access</string>

4. 编写代码

下面是一个完整的示例,展示如何使用picture_cropper插件:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Picture Cropper Example'),
        ),
        body: Center(
          child: MyHomePage(),
        ),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final ImagePicker _picker = ImagePicker();
  late File? _imageFile;

  Future<void> _pickImage() async {
    final XFile? image = await _picker.pickImage(source: ImageSource.camera);

    if (image != null && image.path != null) {
      final File croppedFile = await _cropImage(File(image.path!));
      setState(() {
        _imageFile = croppedFile;
      });
    }
  }

  Future<File> _cropImage(File imageFile) async {
    final CropperController cropperController = CropperController();
    final CroppedFile croppedFile = await PictureCropper.cropImage(
      sourcePath: imageFile.absolute.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,
      ),
      cropperController: cropperController,
    );

    if (croppedFile != null) {
      return File(croppedFile.path);
    } else {
      throw Exception('Crop failed.');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        ElevatedButton(
          onPressed: _pickImage,
          child: Text('Pick and Crop Image'),
        ),
        if (_imageFile != null)
          Image.file(
            _imageFile!,
            width: 300,
            height: 300,
            fit: BoxFit.cover,
          ),
      ],
    );
  }
}

5. 运行应用

现在你可以运行你的Flutter应用,点击按钮从相机中选择图片并进行裁剪。裁剪后的图片会显示在界面上。

这个示例展示了基本的图片选择和裁剪功能,你可以根据需要进一步自定义和扩展。

回到顶部