Flutter图片裁剪插件crop的使用
Flutter图片裁剪插件crop的使用
简介
crop
是一个用于Flutter的裁剪包,它可以裁剪任何小部件,而不仅仅是图像。该包完全用Dart编写,并支持Android、iOS、Web和Desktop平台。由于它独立于本地平台,因此不会增加应用程序输出(如APK)的大小。
- Pub Package
- 支持平台:
- Flutter Android
- Flutter iOS
- Flutter Web
- Flutter Desktop
- Web Demo
- Install from Google Play
开始使用
添加依赖
在你的 pubspec.yaml
文件中添加:
dependencies:
crop: any
导入库
然后,在你的代码中导入:
import 'package:crop/crop.dart';
示例代码
下面是一个完整的示例代码,展示了如何使用 crop
插件来实现图片裁剪功能:
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:crop/crop.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:permission_handler/permission_handler.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Crop Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
useMaterial3: true,
brightness: Brightness.dark,
),
home: const HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final controller = CropController(aspectRatio: 1000 / 667.0);
double _rotation = 0;
BoxShape shape = BoxShape.rectangle;
void _cropImage() async {
final pixelRatio = MediaQuery.of(context).devicePixelRatio;
final cropped = await controller.crop(pixelRatio: pixelRatio);
if (cropped == null) {
return;
}
if (!mounted) {
return;
}
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Scaffold(
appBar: AppBar(
title: const Text('Crop Result'),
centerTitle: true,
actions: [
Builder(
builder: (context) => IconButton(
icon: const Icon(Icons.save),
onPressed: () async {
final status = await Permission.storage.request();
if (status == PermissionStatus.granted) {
await _saveScreenShot(cropped);
if (!mounted) {
return;
}
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Saved to gallery.'),
),
);
}
},
),
),
],
),
body: Center(
child: RawImage(
image: cropped,
),
),
),
fullscreenDialog: true,
),
);
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Scaffold(
appBar: AppBar(
title: const Text('Crop Demo'),
centerTitle: true,
leading: IconButton(
icon: const Icon(Icons.link),
onPressed: () {
launchUrl(Uri.parse('https://github.com/xclud/flutter_crop'), mode: LaunchMode.externalApplication);
},
),
actions: <Widget>[
IconButton(
onPressed: _cropImage,
tooltip: 'Crop',
icon: const Icon(Icons.crop),
)
],
),
body: Column(
children: <Widget>[
Expanded(
child: Container(
color: Colors.black,
padding: const EdgeInsets.all(8),
child: Crop(
onChanged: (decomposition) {
if (_rotation != decomposition.rotation) {
setState(() {
_rotation = ((decomposition.rotation + 180) % 360) - 180;
});
}
},
controller: controller,
shape: shape,
foreground: IgnorePointer(
child: Container(
alignment: Alignment.bottomRight,
child: const Text(
'Foreground Object',
style: TextStyle(color: Colors.red),
),
),
),
helper: shape == BoxShape.rectangle
? Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.white, width: 2),
),
)
: null,
child: Image.asset(
'images/sample.jpg',
fit: BoxFit.cover,
),
),
),
),
Row(
children: <Widget>[
IconButton(
icon: const Icon(Icons.undo),
tooltip: 'Undo',
onPressed: () {
controller.rotation = 0;
controller.scale = 1;
controller.offset = Offset.zero;
setState(() {
_rotation = 0;
});
},
),
Expanded(
child: SliderTheme(
data: theme.sliderTheme.copyWith(
trackShape: CenteredRectangularSliderTrackShape(),
),
child: Slider(
divisions: 360,
value: _rotation,
min: -180,
max: 180,
label: '$_rotation°',
onChanged: (n) {
setState(() {
_rotation = n.roundToDouble();
controller.rotation = _rotation;
});
},
),
),
),
PopupMenuButton<BoxShape>(
icon: const Icon(Icons.crop_free),
itemBuilder: (context) => [
const PopupMenuItem(
value: BoxShape.rectangle,
child: Text("Box"),
),
const PopupMenuItem(
value: BoxShape.circle,
child: Text("Oval"),
),
],
tooltip: 'Crop Shape',
onSelected: (x) {
setState(() {
shape = x;
});
},
),
PopupMenuButton<double>(
icon: const Icon(Icons.aspect_ratio),
itemBuilder: (context) => [
const PopupMenuItem(
value: 1000 / 667.0,
child: Text("Original"),
),
const PopupMenuDivider(),
const PopupMenuItem(
value: 16.0 / 9.0,
child: Text("16:9"),
),
const PopupMenuItem(
value: 4.0 / 3.0,
child: Text("4:3"),
),
const PopupMenuItem(
value: 1,
child: Text("1:1"),
),
const PopupMenuItem(
value: 3.0 / 4.0,
child: Text("3:4"),
),
const PopupMenuItem(
value: 9.0 / 16.0,
child: Text("9:16"),
),
],
tooltip: 'Aspect Ratio',
onSelected: (x) {
controller.aspectRatio = x;
setState(() {});
},
),
],
),
],
),
);
}
}
Future<dynamic> _saveScreenShot(ui.Image img) async {
var byteData = await img.toByteData(format: ui.ImageByteFormat.png);
var buffer = byteData!.buffer.asUint8List();
final result = await ImageGallerySaver.saveImage(buffer);
return result;
}
关键点说明
- 添加依赖:确保在
pubspec.yaml
中正确添加了crop
依赖。 - 导入库:在 Dart 文件中导入
crop
包。 - 创建控制器:使用
CropController
来控制裁剪操作。 - 设置裁剪区域:通过
Crop
小部件设置裁剪区域,并配置其属性如aspectRatio
和shape
。 - 处理裁剪结果:通过
controller.crop()
方法获取裁剪后的图像,并将其保存到相册或进行其他处理。
希望这个示例能帮助你更好地理解和使用 crop
插件!如果有任何问题,欢迎随时提问。
更多关于Flutter图片裁剪插件crop的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter图片裁剪插件crop的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter中使用image_cropper
插件来实现图片裁剪功能的示例代码。这个插件允许你选择一个图片并进行裁剪。
首先,你需要在你的pubspec.yaml
文件中添加image_cropper
依赖:
dependencies:
flutter:
sdk: flutter
image_cropper: ^3.0.1 # 请注意版本号,使用最新的稳定版本
然后运行flutter pub get
来安装依赖。
接下来,你需要请求必要的权限(主要是读写存储权限),并在你的Flutter应用中实现图片选择和裁剪功能。以下是一个完整的示例:
import 'package:flutter/material.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:io';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Image Cropper Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
File? _imageFile;
Future<void> _pickImage() async {
final picker = ImagePicker();
final pickedFile = await picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
final 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(() {
_imageFile = croppedFile;
});
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Image Cropper Example'),
),
body: Center(
child: _imageFile == null
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('No image selected.'),
SizedBox(height: 20.0),
ElevatedButton(
onPressed: _pickImage,
child: Text('Pick an image'),
),
],
)
: Image.file(_imageFile!),
),
);
}
}
在这个示例中,我们做了以下几件事:
- 使用
ImagePicker
插件从设备的图库中选择一个图片。 - 使用
ImageCropper
插件对选择的图片进行裁剪。 - 在UI中显示裁剪后的图片。
注意:
- 你需要添加适当的权限请求到你的
AndroidManifest.xml
和Info.plist
文件中,以便能够访问设备的存储。 - 在Android上,你可能需要在
MainActivity.kt
或MainActivity.java
中处理权限请求。
以下是Android权限请求的示例(在MainActivity.kt
中):
package com.example.yourapp
import android.Manifest
import android.content.pm.PackageManager
import androidx.annotation.NonNull
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
private val REQUEST_IMAGE_CAPTURE = 10
private val PERMISSIONS_REQUEST_CODE_STORAGE = 200
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == PERMISSIONS_REQUEST_CODE_STORAGE) {
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
// Permission granted
} else {
// Permission denied
}
}
}
override fun onStart() {
super.onStart()
if (ContextCompat.checkSelfPermission(
this.applicationContext,
Manifest.permission.READ_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(
this.applicationContext,
Manifest.permission.WRITE_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE),
PERMISSIONS_REQUEST_CODE_STORAGE
)
}
}
}
在iOS上,你需要在Info.plist
中添加以下权限:
<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to your photo library to pick images</string>
<key>NSCameraUsageDescription</key>
<string>We need access to your camera to take photos</string>
<key>NSMicrophoneUsageDescription</key>
<string>We need access to your microphone</string>
这样,你就可以在Flutter应用中使用image_cropper
插件来实现图片裁剪功能了。