image_picker_kit 1.0.1
image_picker_kit: ^1.0.1 copied to clipboard
A complete, all-in-one Flutter plugin for image workflow: pick, crop, and compress. This package provides native implementation (MethodChannel) for picking and compressing, while integrating the 'imag [...]
Image Picker Kit #
A complete, all-in-one Flutter plugin for a native image workflow: pick, crop, and compress.
Description #
A complete, all-in-one Flutter plugin for image workflow: pick, crop, and compress. This package provides a native implementation (MethodChannel) for selecting and compressing, while integrating the image_cropper library. Native Compression (Pick-only) utilises the native compressors Bitmap.compress for Android and UIImage.jpegData for iOS. While cropping, it utilises image_cropper's built-in compression parameters.
Installation #
-
Add the package to your
pubspec.yaml:dependencies: image_picker_kit: ^1.0.0 # Replace with the latest version -
Run
flutter pub get.
Platform Setup #
This plugin requires native setup on both iOS and Android.
iOS #
Add the NSPhotoLibraryUsageDescription key to your ios/Runner/Info.plist file. This is required for any app that accesses the photo library.
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs access to the photo library to select and crop images.</string>
Android #
You must complete all three steps for the plugin to work correctly on Android.
- Add UCropActivity to AndroidManifest.xml
The integrated image_cropper plugin requires the UCropActivity. Add it inside the
<manifest ...>
<application ...>
<activity android:name=".MainActivity" ...>
</activity>
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
<meta-data ... />
</application>
</manifest>
- Enable MultiDex
Adding native plugins can cause your app to exceed Android's 64K method limit. Enable multiDex in your android/app/build.gradle.kts (or .gradle) file. This allows your app to be split into multiple .dex files, preventing crashes on older Android versions.
android {
defaultConfig {
// ...
multiDexEnabled = true
}
}
- Add ExifInterface Dependency
To prevent a NoClassDefFoundError when the cropper tries to read image rotation and metadata, add the exifinterface dependency to your android/app/build.gradle.kts. This manually includes the ExifInterface class, which uCrop needs but is sometimes removed by build tools.
dependencies {
implementation("androidx.exifinterface:exifinterface:1.3.7")
// ... other dependencies
}
Usage #
Import the package and create an instance of MediaPickerKit.
import 'package.image_picker_kit/image_picker_kit.dart';
// Create an instance of the kit
final MediaPickerKit _pickerKit = MediaPickerKit();
- Pick Image This method picks an image and uses the native compressor.
Future<void> selectImage() async {
final File? resultFile = await _pickerKit.pickImageFromGallery(
compressQuality: 80, // 1-100
);
if (resultFile != null) {
// Use the compressed file
} else {
// User cancelled
}
}
- Pick and Crop Image This method picks an image, opens the cropper UI, and uses the image_cropper's built-in compression.
Future<void> selectAndCropImage() async {
final File? resultFile = await _pickerKit.pickAndCropImageFromGallery(
// These settings are passed to image_cropper
compressQuality: 80, // 1-100
compressFormat: ImageCompressFormat.jpg,
aspectRatio: const CropAspectRatio(ratioX: 16, ratioY: 9),
androidUiSettings: const AndroidUiSettings(
toolbarTitle: 'Crop Image',
toolbarColor: Colors.blue,
toolbarWidgetColor: Colors.white,
),
iOSUiSettings: const IOSUiSettings(
title: 'Crop Image',
),
);
if (resultFile != null) {
// Use the cropped and compressed file
} else {
// User cancelled
}
}
Full Example #
Here is a simple example of how to use both methods.
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker_kit/image_picker_kit.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final MediaPickerKit _pickerKit = MediaPickerKit();
String _resultMessage = 'No image chosen yet';
File? _imageFile;
Future<void> _handlePickingLogic(Future<File?> Function() pickingFuture) async {
setState(() {
_resultMessage = 'Loading...';
_imageFile = null;
});
final File? resultFile = await pickingFuture();
setState(() {
if (resultFile != null) {
_resultMessage = 'SUCCESS';
_imageFile = resultFile;
} else {
_resultMessage = 'CANCELLED';
_imageFile = null;
}
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Image Picker Kit Example')),
body: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () => _handlePickingLogic(
() => _pickerKit.pickImageFromGallery(compressQuality: 10),
),
child: const Text('Pick (Only) & Compress'),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () => _handlePickingLogic(
() => _pickerKit.pickAndCropImageFromGallery(compressQuality: 10),
),
child: const Text('Pick, Crop & Compress'),
),
const SizedBox(height: 20),
Text(_resultMessage),
const SizedBox(height: 20),
if (_imageFile != null)
Image.file(
_imageFile!,
height: 300,
width: 300,
fit: BoxFit.cover,
)
else
Container(
height: 300,
width: 300,
color: Colors.grey[300],
alignment: Alignment.center,
child: const Text('Image Preview'),
),
],
),
),
),
),
);
}
}
Credits #
This package provides a unified API and custom native implementations for picking/compressing, but the powerful cropping UI is provided entirely by the image_cropper package.