Flutter媒体选择器插件vs_media_picker的使用
Flutter媒体选择器插件vs_media_picker的使用
简介
VS_Media_Picker
是基于 photo_widget
包开发的,其概念与 image_picker
类似,但提供了更吸引人的界面来从设备图库中选择图片或视频,支持Android和iOS平台。
功能
- [✔] 选择图片
- [✔] 选择视频
- [✔] 多选图片/视频
- [✔] 封面缩略图(预览图库中的第一张图片)
- [❌] 从相机拍摄图片或视频(不支持)
示例演示
安装
- 在
pubspec.yaml
文件中添加vs_media_picker: 0.0.2
。 - 导入
vs_media_picker
包:import 'package:vs_media_picker/vs_media_picker.dart';
配置
Android
- 更新
build.gradle
文件中的 Kotlin 版本为1.6.0
和classpath 'com.android.tools.build:gradle:7.0.4'
。 - 设置
minSdkVersion
为25
。 - 在
AndroidManifest.xml
文件中添加权限:<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
iOS
在 info.plist
文件中添加以下配置:
<key>NSPhotoLibraryUsageDescription</key>
<string>访问相册权限说明</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>添加到相册权限说明</string>
使用方法
创建一个 VSMediaPicker
小部件:
Material(
child: VSMediaPicker(
pathList: (pathList) {
// pathList 是一个包含选定媒体元数据的列表
// 每个元素是一个 PickedAssetModel 对象
// 可以根据需要处理这些数据
},
maxPickImages: 5, // 最多选择5张图片
singlePick: false, // 是否单选
appBarColor: Colors.blue, // 标题栏颜色
albumBackGroundColor: Colors.grey[800], // 相册背景颜色
albumDividerColor: Colors.grey[700], // 相册分隔线颜色
albumTextColor: Colors.white, // 相册文字颜色
appBarIconColor: Colors.white, // 标题栏图标颜色
appBarTextColor: Colors.white, // 标题栏文字颜色
crossAxisCount: 3, // 每行显示的图片数量
gridViewBackgroundColor: Colors.grey[900], // 图片网格背景颜色
childAspectRatio: 1, // 图片宽高比
imageBackgroundColor: Colors.black, // 图片背景颜色
selectedBackgroundColor: Colors.black, // 选中项背景颜色
selectedCheckColor: Colors.white, // 选中项勾选颜色
thumbnailBoxFix: BoxFit.cover, // 缩略图填充方式
onlyImages: true, // 仅显示图片
thumbnailQuality: 200, // 缩略图质量
),
);
完整示例Demo
以下是一个完整的示例代码,展示了如何使用 VS_Media_Picker
插件来选择图片并显示在应用中:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:share_plus/share_plus.dart';
import 'package:vs_media_picker/vs_media_picker.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(statusBarColor: Colors.black));
runApp(MultiProvider(
providers: [ChangeNotifierProvider(create: (_) => PickerDataProvider())],
child: const MyApp(),
));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: const ViewMedia(),
);
}
}
class ViewMedia extends StatefulWidget {
const ViewMedia({Key? key}) : super(key: key);
[@override](/user/override)
State<ViewMedia> createState() => _ViewMediaState();
}
class _ViewMediaState extends State<ViewMedia> {
PickedAssetModel? data;
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: ListView(
children: [
TextButton(
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute<PickedAssetModel>(
builder: (BuildContext context) => const Example(),
))
.then((value) {
if (value != null) {
setState(() {
data = value;
});
}
});
},
child: const Text(
"点击选择图片",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
),
const SizedBox(height: 30),
data == null
? const SizedBox()
: SizedBox(
height: 500,
child: Image.file(File(data!.path!)),
)
],
),
);
}
}
class Example extends StatefulWidget {
const Example({Key? key}) : super(key: key);
[@override](/user/override)
State<Example> createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
bool _singlePick = false;
[@override](/user/override)
Widget build(BuildContext context) {
return SafeArea(
child: Consumer<PickerDataProvider>(
builder: (context, media, _) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
onPressed: () {
if (media.pickedFile.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("未选择媒体文件")),
);
} else {
Navigator.of(context).pop(media.pickedFile[0]);
}
},
icon: const Icon(Icons.done),
)
],
),
body: Column(
children: [
Container(
height: 300,
color: Colors.black,
child: media.pickedFile.isEmpty
? Container(
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Transform.scale(
scale: 8,
child: const Icon(
Icons.image_outlined,
color: Colors.white,
size: 10,
),
),
const SizedBox(height: 50),
const Text(
'未选择图片',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: Colors.white70),
)
],
),
)
: PageView(
children: media.pickedFile.map((data) {
if (data.type == 'image') {
return Center(
child: PhotoView.customChild(
enablePanAlways: true,
maxScale: 2.0,
minScale: 1.0,
child: Image.file(File(data.path!)),
),
);
} else {
return Container();
}
}).toList(),
),
),
Expanded(
child: VSMediaPicker(
childAspectRatio: 1,
crossAxisCount: 3,
thumbnailQuality: 200,
onlyImages: true,
thumbnailBoxFix: BoxFit.cover,
singlePick: _singlePick,
gridViewBackgroundColor: Colors.grey[900]!,
imageBackgroundColor: Colors.black,
maxPickImages: 5,
appBarHeight: 60,
selectedBackgroundColor: Colors.black,
selectedCheckColor: Colors.black87,
selectedCheckBackgroundColor: Colors.white10,
pathList: (paths) {
setState(() {
media.pickedFile = paths;
});
},
appBarLeadingWidget: Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(right: 15, bottom: 12),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
height: 30,
child: Container(
alignment: Alignment.centerRight,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
GestureDetector(
onTap: () {
setState(() {
_singlePick = !_singlePick;
});
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
border: Border.all(color: Colors.blue, width: 1.5),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'多选',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 10),
),
const SizedBox(width: 7),
Transform.scale(
scale: 1.5,
child: Icon(
_singlePick
? Icons.check_box_outline_blank
: Icons.check_box_outlined,
color: Colors.blue,
size: 10,
),
)
],
),
),
),
),
],
),
),
),
const Spacer(),
GestureDetector(
onTap: () async {
List<XFile> mediaPath = [];
for (var p in media.pickedFile) {
mediaPath.add(XFile(p.path!));
}
if (mediaPath.isNotEmpty) {
await Share.shareXFiles(mediaPath);
}
mediaPath.clear();
},
child: Container(
height: 30,
width: 30,
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.blue, width: 1.5),
),
child: Transform.scale(
scale: 2,
child: const Icon(
Icons.share_outlined,
color: Colors.blue,
size: 10,
),
),
),
)
],
),
),
),
),
)
],
),
);
},
),
);
}
}
class PickerDataProvider with ChangeNotifier {
List<PickedAssetModel> pickedFile = [];
void updatePickedFile(List<PickedAssetModel> newFiles) {
pickedFile = newFiles;
notifyListeners();
}
}
更多关于Flutter媒体选择器插件vs_media_picker的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter媒体选择器插件vs_media_picker的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用Flutter中的vs_media_picker
插件来选择媒体文件(图片和视频)的代码示例。vs_media_picker
是一个功能强大的媒体选择器插件,允许用户从设备图库中选择媒体文件。
首先,确保你已经在pubspec.yaml
文件中添加了vs_media_picker
依赖:
dependencies:
flutter:
sdk: flutter
vs_media_picker: ^latest_version # 请替换为最新的版本号
然后运行flutter pub get
来安装依赖。
接下来,在你的Flutter项目中,你可以按照以下步骤使用vs_media_picker
:
- 导入必要的包:
import 'package:flutter/material.dart';
import 'package:vs_media_picker/vs_media_picker.dart';
- 配置和使用
VsMediaPicker
:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<VsMedia?>? selectedMedia;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('vs_media_picker Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () async {
final result = await VsMediaPicker.pickMedia(
context: context,
maxVideos: 1,
maxImages: 5,
enableCamera: true,
videoQuality: CameraVideoQuality.high,
selectedAssets: selectedMedia?.cast<VsMedia>(),
);
if (result != null) {
setState(() {
selectedMedia = result;
});
}
},
child: Text('Select Media'),
),
SizedBox(height: 20),
if (selectedMedia != null)
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 4.0,
mainAxisSpacing: 4.0,
),
itemCount: selectedMedia!.length,
itemBuilder: (context, index) {
final media = selectedMedia![index];
if (media == null) return Container();
return Image.file(
File(media.path),
fit: BoxFit.cover,
);
},
),
],
),
),
);
}
}
在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个按钮用于启动媒体选择器。用户可以选择图片和视频,选中的媒体文件将显示在一个GridView中。
代码解释:
- 依赖导入:我们导入了
flutter/material.dart
和vs_media_picker/vs_media_picker.dart
。 - UI结构:我们使用了一个Scaffold,其中包含一个AppBar和一个Column。Column中有一个按钮用于启动媒体选择器,以及一个GridView用于显示选中的媒体文件。
- 媒体选择器:我们使用
VsMediaPicker.pickMedia
方法来启动媒体选择器。这个方法允许我们配置一些参数,比如最大视频和图片数量、是否启用相机、视频质量等。 - 显示选中的媒体:选中的媒体文件保存在
selectedMedia
列表中,我们在GridView中遍历这个列表并显示每张图片。
请确保你的应用有读取存储权限(特别是在Android上),这通常需要在AndroidManifest.xml
中添加相关权限声明,并在运行时请求权限(如果需要的话)。
希望这个示例能帮你更好地理解如何使用vs_media_picker
插件!