Flutter图片选择插件image_pickers的使用
Flutter图片选择插件image_pickers的使用
image_pickers
是一个功能强大的Flutter插件,支持本地图片和视频的多选、网络图片保存到相册、截图保存到相册、网络视频保存到相册等功能。它还支持预览图片和视频,并允许自定义主题颜色。
插件特性
- 支持多选本地图片和视频
- 支持将网络图片和视频保存到相册
- 支持截图保存到相册
- 支持预览图片和视频
- 支持设置主题颜色
支持平台
- Android
- iOS
注意事项
对于Android项目,请确保在 build.gradle
文件中指定以下版本:
targetSdkVersion 33
compileSdkVersion 33
否则,在Android 13上可能会出现无法正常访问图片的问题。
使用方法
添加依赖
在 pubspec.yaml
文件中添加以下依赖:
dependencies:
image_pickers: ^2.0.5+2
导入包
在需要使用的文件中导入插件:
import 'package:image_pickers/image_pickers.dart';
示例代码
以下是一个完整的示例应用,展示如何使用 image_pickers
插件来选择图片和视频、拍摄照片和视频、预览和保存媒体文件。
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:image_pickers/image_pickers.dart';
import 'dart:ui' as ui;
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
GlobalKey? globalKey;
@override
void initState() {
super.initState();
globalKey = GlobalKey();
}
List<Media> _listImagePaths = [];
List<Media> _listVideoPaths = [];
List<Media> _listImageVideoPaths = [];
String? dataImagePath = "";
@override
Widget build(BuildContext context) {
return RepaintBoundary(
key: globalKey,
child: MaterialApp(
theme: ThemeData(
primaryColor: Colors.white,
),
home: Scaffold(
appBar: AppBar(
title: const Text('多图选择'),
),
body: SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Column(
children: <Widget>[
GridView.builder(
physics: NeverScrollableScrollPhysics(),
itemCount: _listImagePaths.length,
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 20.0,
crossAxisSpacing: 10.0,
childAspectRatio: 1.0),
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
ImagePickers.previewImagesByMedia(
_listImagePaths, index);
},
child: Image.file(
File(
_listImagePaths[index].path!,
),
fit: BoxFit.cover,
),
);
}),
ElevatedButton(
onPressed: () async {
_listImagePaths = await ImagePickers.pickerPaths(
galleryMode: GalleryMode.image,
showGif: true,
selectCount: 5,
showCamera: true,
cropConfig: CropConfig(enableCrop: true),
compressSize: 500,
uiConfig: UIConfig(uiThemeColor: Color(0xffff0000)),
);
print(_listImagePaths);
if (_listImagePaths.length > 0) {
_listImagePaths.forEach((media) {
print(media);
});
}
setState(() {});
},
child: Text("选择图片"),
),
ElevatedButton(
onPressed: () async {
ImagePickers.openCamera(
cropConfig: CropConfig(
enableCrop: true, width: 2, height: 3))
.then((Media? media) {
_listImagePaths.clear();
if (media != null) {
_listImagePaths.add(media);
print(media.toString());
}
setState(() {});
});
},
child: Text("拍照"),
),
ElevatedButton(
onPressed: () {
ImagePickers.openCamera(
cameraMimeType: CameraMimeType.video,
videoRecordMinSecond: 3,
videoRecordMaxSecond: 10)
.then((media) {
_listVideoPaths.clear();
if (media != null) {
print(media.toString());
_listVideoPaths.add(media);
}
setState(() {});
});
},
child: Text("拍视频"),
),
GridView.builder(
physics: NeverScrollableScrollPhysics(),
itemCount: _listVideoPaths.length,
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 20.0,
crossAxisSpacing: 10.0,
childAspectRatio: 1.0),
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
ImagePickers.previewVideo(
_listVideoPaths[index].path!,
);
},
child: Image.file(
File(
_listVideoPaths[index].thumbPath!,
),
fit: BoxFit.cover,
),
);
}),
ElevatedButton(
onPressed: () async {
_listVideoPaths = await ImagePickers.pickerPaths(
galleryMode: GalleryMode.video,
videoRecordMinSecond: 3,
videoRecordMaxSecond: 10,
selectCount: 2,
showCamera: true,
);
setState(() {});
print(_listVideoPaths);
},
child: Text("选择视频"),
),
GridView.builder(
physics: NeverScrollableScrollPhysics(),
itemCount: _listImageVideoPaths.length,
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 20.0,
crossAxisSpacing: 10.0,
childAspectRatio: 1.0),
itemBuilder: (BuildContext context, int index) {
Media media = _listImageVideoPaths[index];
return GestureDetector(
onTap: () {
ImagePickers.previewImagesByMedia(
_listImageVideoPaths, index);
},
child: Image.file(
File(
_listImageVideoPaths[index].thumbPath!,
),
fit: BoxFit.cover,
),
);
}),
ElevatedButton(
onPressed: () async {
_listImageVideoPaths = await ImagePickers.pickerPaths(
galleryMode: GalleryMode.all,
selectCount: 8,
showCamera: true,
videoRecordMinSecond: 3,
videoRecordMaxSecond: 10,
videoSelectMinSecond: 5,
);
setState(() {});
print(_listImageVideoPaths);
},
child: Text("选择图片和视频"),
),
InkWell(
onTap: () {
ImagePickers.previewImage(
"http://i1.sinaimg.cn/ent/d/2008-06-04/U105P28T3D2048907F326DT20080604225106.jpg");
},
child: Image.network(
"http://i1.sinaimg.cn/ent/d/2008-06-04/U105P28T3D2048907F326DT20080604225106.jpg",
fit: BoxFit.cover,
width: 100,
height: 100,
)),
ElevatedButton(
onPressed: () {
Future<String?> future = ImagePickers.saveImageToGallery(
"http://i1.sinaimg.cn/ent/d/2008-06-04/U105P28T3D2048907F326DT20080604225106.jpg");
future.then((path) {
print("保存图片路径:" + path!);
});
},
child: Text("保存网络图片"),
),
dataImagePath == ""
? Container()
: GestureDetector(
onTap: () {
ImagePickers.previewImage(dataImagePath!);
},
child: Image.file(
File(dataImagePath!),
fit: BoxFit.cover,
width: 100,
height: 100,
)),
ElevatedButton(
onPressed: () async {
RenderRepaintBoundary boundary = globalKey!.currentContext!
.findRenderObject() as RenderRepaintBoundary;
ui.Image image = await boundary.toImage(pixelRatio: 3);
ByteData byteData = await image.toByteData(
format: ui.ImageByteFormat.png) as ByteData;
Uint8List data = byteData.buffer.asUint8List();
dataImagePath =
await ImagePickers.saveByteDataImageToGallery(
data,
);
print("保存截屏图片 = " + dataImagePath!);
setState(() {});
},
child: Text("保存截屏图片"),
),
ElevatedButton(
onPressed: () {
Future<String?> future = ImagePickers.saveVideoToGallery(
"http://vd4.bdstatic.com/mda-jbmn50510sid5yx5/sc/mda-jbmn50510sid5yx5.mp4");
future.then((path) {
print("视频保存成功" + path!);
});
},
child: Text("保存视频"),
),
],
),
),
),
),
);
}
}
iOS配置
在 Info.plist
文件中添加以下条目:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSMicrophoneUsageDescription</key>
<string>...</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>...</string>
<key>NSCameraUsageDescription</key>
<string>...</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>...</string>
通过以上步骤和示例代码,您可以轻松地在Flutter应用中集成图片和视频选择功能。希望这对您有所帮助!
更多关于Flutter图片选择插件image_pickers的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter图片选择插件image_pickers的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter应用中使用image_picker
插件来选择图片的示例代码。这个示例将展示如何集成image_picker
插件,以及如何使用它来从设备的图库或相机中选择图片,并在UI中显示。
第一步:添加依赖
首先,在你的pubspec.yaml
文件中添加image_picker
依赖:
dependencies:
flutter:
sdk: flutter
image_picker: ^latest_version # 请替换为最新版本号
然后运行flutter pub get
来安装依赖。
第二步:请求权限
在Android和iOS上,选择图片通常需要请求存储或相机权限。你可以在AndroidManifest.xml
和Info.plist
中添加必要的权限声明,但更重要的是,在运行时请求这些权限。Flutter的image_picker
插件已经为你处理了大部分权限请求的逻辑,但你可能需要在代码中显式处理权限被拒绝的情况。
第三步:使用image_picker
选择图片
以下是一个完整的Flutter应用示例,它展示了如何使用image_picker
插件来选择图片并在Image.widget中显示:
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Image Picker Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ImagePickerScreen(),
);
}
}
class ImagePickerScreen extends StatefulWidget {
@override
_ImagePickerScreenState createState() => _ImagePickerScreenState();
}
class _ImagePickerScreenState extends State<ImagePickerScreen> {
final _picker = ImagePicker();
File? _imageFile;
Future<void> _pickImage(ImageSource source) async {
final pickedFile = await _picker.pickImage(source: source);
if (pickedFile != null) {
setState(() {
_imageFile = File(pickedFile.path);
});
} else {
print('No image selected.');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Image Picker Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
if (_imageFile != null)
Image.file(
_imageFile!,
width: 300,
height: 300,
fit: BoxFit.cover,
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () => _pickImage(ImageSource.gallery),
child: Text('Pick Image from Gallery'),
),
SizedBox(height: 10),
ElevatedButton(
onPressed: () => _pickImage(ImageSource.camera),
child: Text('Pick Image from Camera'),
),
],
),
),
);
}
}
说明
- 依赖添加:在
pubspec.yaml
中添加image_picker
依赖。 - 状态管理:使用
StatefulWidget
来管理图片文件的状态。 - 选择图片:定义
_pickImage
方法,它接受一个ImageSource
枚举(gallery
或camera
),并调用_picker.pickImage
方法来选择图片。 - 显示图片:如果选择了图片,使用
Image.file
来显示图片。 - 按钮:提供两个按钮,一个用于从图库中选择图片,另一个用于从相机中选择图片。
确保在实际部署到iOS或Android设备之前,根据平台要求配置必要的权限和设置。对于iOS,你需要在Info.plist
中添加相机和照片库的权限请求。对于Android,你需要在AndroidManifest.xml
中声明这些权限,并可能需要在运行时请求它们(尽管image_picker
插件已经为你处理了大部分逻辑)。