Flutter中如何从相册选取多个视频并展示
实现Flutter相册多选视频并展示的完整方案
我来帮你搞定Flutter里多选相册视频并展示的需求,这是一套经过验证的完整方案:
1. 引入必要的依赖
先在pubspec.yaml里添加三个关键依赖:
image_picker:官方维护的媒体选择器,支持多选指定类型的媒体video_player:用于播放和展示选中的视频permission_handler:处理权限申请,确保能正常访问相册
dependencies: flutter: sdk: flutter image_picker: ^1.0.7 video_player: ^2.8.0 permission_handler: ^10.2.0
添加后执行flutter pub get安装依赖。
2. 配置平台权限
Android配置
打开android/app/src/main/AndroidManifest.xml,添加对应权限:
<!-- Android 13+ 专属视频访问权限 --> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <!-- Android 12及以下 外部存储访问权限 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
iOS配置
打开ios/Runner/Info.plist,添加权限说明(必须填写,否则App会被拒):
<key>NSPhotoLibraryUsageDescription</key> <string>需要访问您的相册以选择视频</string>
3. 完整功能实现代码
下面是包含权限申请、视频多选、视频展示的可直接运行代码:
import 'dart:io'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:video_player/video_player.dart'; class MultiVideoPickerScreen extends StatefulWidget { const MultiVideoPickerScreen({super.key}); @override State<MultiVideoPickerScreen> createState() => _MultiVideoPickerScreenState(); } class _MultiVideoPickerScreenState extends State<MultiVideoPickerScreen> { final ImagePicker _picker = ImagePicker(); List<XFile> _selectedVideos = []; List<VideoPlayerController?> _videoControllers = []; // 申请相册权限 Future<bool> _requestGalleryPermission() async { final status = await Permission.photos.request(); return status.isGranted; } // 选择多个视频 Future<void> _pickVideos() async { final hasPermission = await _requestGalleryPermission(); if (!hasPermission) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('需要授予相册权限才能选择视频')), ); return; } final List<XFile>? pickedVideos = await _picker.pickMedia( mediaType: MediaType.video, allowMultiple: true, ); if (pickedVideos != null && pickedVideos.isNotEmpty) { setState(() { _selectedVideos = pickedVideos; }); _initVideoControllers(); } } // 初始化所有选中视频的播放控制器 void _initVideoControllers() { _videoControllers = List.generate( _selectedVideos.length, (index) => VideoPlayerController.file( File(_selectedVideos[index].path), )..initialize().then((_) { setState(() {}); }), ); } // 页面销毁时释放控制器,避免内存泄漏 @override void dispose() { for (var controller in _videoControllers) { controller?.dispose(); } super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('多选视频展示')), body: Column( children: [ Padding( padding: const EdgeInsets.all(16), child: ElevatedButton( onPressed: _pickVideos, child: const Text('从相册选择视频'), ), ), Expanded( child: _selectedVideos.isEmpty ? const Center(child: Text('暂无选中的视频')) : GridView.builder( padding: const EdgeInsets.symmetric(horizontal: 16), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 12, mainAxisSpacing: 12, ), itemCount: _selectedVideos.length, itemBuilder: (context, index) { final controller = _videoControllers[index]; return controller != null && controller.value.isInitialized ? GestureDetector( onTap: () { setState(() { controller.value.isPlaying ? controller.pause() : controller.play(); }); }, child: Stack( alignment: Alignment.center, children: [ VideoPlayer(controller), if (!controller.value.isPlaying) const Icon( Icons.play_circle_fill, size: 48, color: Colors.white, ), ], ), ) : const Center(child: CircularProgressIndicator()); }, ), ), ], ), ); } } // 测试入口 void main() => runApp(const MaterialApp(home: MultiVideoPickerScreen()));
4. 关键注意事项
- 权限前置检查:必须先申请权限再打开相册,否则会直接被系统拒绝访问
- 控制器内存管理:每个视频对应一个
VideoPlayerController,一定要在页面销毁时释放,避免内存泄漏 - 性能优化:如果需要支持大量视频选中,建议做懒加载控制器或者限制选中数量,防止内存占用过高
- 平台适配:Android 13+和旧版本的权限配置不同,一定要按步骤配置
内容的提问来源于stack exchange,提问作者hardik koladiya
相关产品推荐
相关产品推荐

