Flutter图片裁剪插件dynamic_image_crop的使用
Flutter图片裁剪插件dynamic_image_crop的使用
dynamic_image_crop
是一个用于在Flutter中裁剪图片成各种形状的插件。本文将详细介绍如何使用这个插件,并提供一个完整的示例demo。
介绍
dynamic_image_crop
支持将图片裁剪为用户绘制的形状,以及矩形、圆形和三角形等形状。它还允许更改裁剪形状线的颜色和宽度。
你可以通过以下链接测试该插件:demo_link
特性
- 支持将图片裁剪为用户绘制的形状。
- 支持将图片裁剪为矩形、圆形和三角形形状。
- 支持更改裁剪形状线的颜色。
- 支持更改裁剪形状线的宽度。
使用方法
安装
首先,在你的pubspec.yaml
文件中添加dynamic_image_crop
依赖:
dependencies:
flutter:
sdk: flutter
dynamic_image_crop: ^latest_version
然后运行flutter pub get
以安装依赖。
示例代码
以下是完整的示例代码,展示了如何使用dynamic_image_crop
插件进行图片裁剪。
import 'dart:ui';
import 'package:dynamic_image_crop/dynamic_image_crop.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(const TestApp());
}
class TestApp extends StatefulWidget {
const TestApp({super.key});
@override
State<TestApp> createState() => _TestAppState();
}
class _TestAppState extends State<TestApp> {
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: CropScreen(),
);
}
}
class CropScreen extends StatefulWidget {
const CropScreen({super.key});
@override
State<CropScreen> createState() => _CropScreenState();
}
class _CropScreenState extends State<CropScreen> {
CropType cropType = CropType.none;
Uint8List? image;
final cropController = CropController();
final urlController = TextEditingController();
final initialUrl = 'https://miro.medium.com/v2/1*bzC0ul7jBVhOJiastVGKlw.png';
@override
void initState() {
urlController.text = initialUrl;
loadImage(initialUrl);
super.initState();
}
void loadImage(
String url, {
void Function(Uint8List)? callback,
ImageByteFormat imageFormat = ImageByteFormat.png,
}) {
Image.network(url).image.resolve(ImageConfiguration.empty).addListener(
ImageStreamListener((info, _) async {
try {
final byteData = await info.image.toByteData(format: imageFormat);
setState(() {
image = byteData!.buffer.asUint8List();
if (image != null) {
callback?.call(image!);
}
});
} catch (e) {
debugPrint('try another image byte format: $e');
}
}),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
floatingActionButtonLocation: FloatingActionButtonLocation.endTop,
floatingActionButton: FloatingActionButton.extended(
onPressed: cropController.cropImage,
backgroundColor: Colors.white,
label: const Text('Crop', style: TextStyle(color: Colors.black)),
),
body: SafeArea(
child: Builder(
builder: (context) {
if (image == null) {
return const Center(child: CircularProgressIndicator());
} else {
return Column(
children: [
Expanded(
child: Center(
child: DynamicImageCrop(
controller: cropController,
image: image!,
onResult: (image, width, height) {
sendResultImage(image, context);
},
),
),
),
Container(
padding: const EdgeInsets.all(16),
color: Colors.black,
child: Center(
child: Column(
children: [
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: buildButtons(),
),
Row(
children: [
Expanded(
child: TextField(
controller: urlController,
decoration: const InputDecoration(
hintText: 'Enter URL',
),
onChanged: (value) {
urlController.text = value;
},
style: const TextStyle(color: Colors.white),
),
),
Padding(
padding: const EdgeInsets.only(left: 8),
child: IconButton(
onPressed: () {
loadImage(
urlController.text,
callback: cropController.changeImage,
);
},
icon: const Icon(
CupertinoIcons.search_circle_fill,
color: Colors.white,
),
),
),
],
),
],
),
),
)
],
);
}
},
),
),
);
}
Widget buildButtons() {
return Row(
children: [
IconButton(
onPressed: () => changeShape(CropType.rectangle),
icon: const Icon(CupertinoIcons.rectangle_fill, color: Colors.white),
),
const SizedBox(width: 8),
IconButton(
onPressed: () => changeShape(CropType.circle),
icon: const Icon(CupertinoIcons.circle_fill, color: Colors.white),
),
const SizedBox(width: 8),
IconButton(
onPressed: () => changeShape(CropType.triangle),
icon: const Icon(CupertinoIcons.triangle_fill, color: Colors.white),
),
const SizedBox(width: 8),
IconButton(
onPressed: () => changeShape(CropType.drawing),
icon: const Icon(CupertinoIcons.pencil_outline, color: Colors.white),
),
const SizedBox(width: 8),
IconButton(
onPressed: cropController.clearCropArea,
icon: const Icon(
CupertinoIcons.clear_circled_solid,
color: Colors.white,
),
),
],
);
}
void changeShape(CropType type) {
cropController.changeType(type);
}
void sendResultImage(
Uint8List? bytes,
BuildContext context,
) {
if (bytes != null) {
Navigator.push(
context,
MaterialPageRoute<dynamic>(
builder: (_) => ResultScreen(
image: bytes,
),
),
);
}
}
}
class ResultScreen extends StatelessWidget {
const ResultScreen({
required this.image,
super.key,
});
final Uint8List image;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
floatingActionButtonLocation: FloatingActionButtonLocation.startTop,
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.white,
onPressed: () => Navigator.pop(context),
child: const Icon(Icons.arrow_back, color: Colors.black),
),
body: Center(
child: Image.memory(
image,
fit: BoxFit.cover,
),
),
);
}
}
控制器方法
CropController
提供了以下方法:
void cropImage() {}
void changeType(CropType type) {}
void changeImage(Uint8List image) {}
void clearCropArea() {}
裁剪类型
CropType
枚举提供了以下类型:
enum CropType {
rectangle, circle, triangle, drawing, none
}
更多关于Flutter图片裁剪插件dynamic_image_crop的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter图片裁剪插件dynamic_image_crop的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用dynamic_image_crop
插件来实现图片裁剪功能的代码示例。这个插件允许用户在设备上动态裁剪图片。
1. 添加依赖
首先,在你的pubspec.yaml
文件中添加dynamic_image_crop
依赖:
dependencies:
flutter:
sdk: flutter
dynamic_image_crop: ^0.1.0 # 请检查最新版本号
然后运行flutter pub get
来安装依赖。
2. 导入插件
在你的Dart文件中导入dynamic_image_crop
插件:
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:dynamic_image_crop/dynamic_image_crop.dart';
注意:dynamic_image_crop
插件通常需要与image_picker
插件一起使用来获取图片。
3. 实现图片选择和裁剪功能
下面是一个完整的示例,展示了如何从图库中选择图片并使用dynamic_image_crop
进行裁剪:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ImageCropScreen(),
);
}
}
class ImageCropScreen extends StatefulWidget {
@override
_ImageCropScreenState createState() => _ImageCropScreenState();
}
class _ImageCropScreenState extends State<ImageCropScreen> {
File? _imageFile;
CroppedFile? _croppedFile;
final ImagePicker _picker = ImagePicker();
Future<void> _pickImage(ImageSource source) async {
final pickedFile = await _picker.pickImage(source: source);
if (pickedFile != null) {
setState(() {
_imageFile = File(pickedFile.path);
});
// 裁剪图片
_cropImage();
}
}
Future<void> _cropImage() async {
if (_imageFile == null) return;
final croppedFile = await ImageCropper().cropImage(
sourcePath: _imageFile!.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(() {
_croppedFile = croppedFile;
});
// 显示裁剪后的图片
showCroppedImage();
}
}
void showCroppedImage() {
if (_croppedFile != null) {
// 这里可以显示裁剪后的图片,例如使用 Image.file(_croppedFile!.path)
print('Cropped image path: ${_croppedFile!.path}');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Image Crop Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_imageFile != null
? Image.file(_imageFile!)
: Text('No image selected.'),
SizedBox(height: 20),
ElevatedButton(
onPressed: () => _pickImage(ImageSource.gallery),
child: Text('Pick from gallery'),
),
SizedBox(height: 10),
ElevatedButton(
onPressed: () => _pickImage(ImageSource.camera),
child: Text('Take a picture'),
),
],
),
),
);
}
}
4. 注意事项
- 确保在
AndroidManifest.xml
和Info.plist
中添加必要的权限和配置,以便访问相机和图库。 - 根据需要调整裁剪设置,例如裁剪比例和UI样式。
这个示例展示了如何使用dynamic_image_crop
插件来选择和裁剪图片。你可以根据实际需求进一步自定义和扩展这个示例。