Flutter媒体选择器插件media_selector_null_safety的使用
Flutter媒体选择器插件media_selector_null_safety的使用
简介
media_selector_null_safety 是一款针对 Android 和 iOS 平台的图片选择器插件,支持从相册获取图片、视频、拍照,支持裁剪(单图或单选或多选裁剪)、压缩、主题自定义配置等功能,并且支持动态获取权限。
导入插件
在 pubspec.yaml 文件中添加以下依赖:
dependencies:
  media_selector_null_safety: ^0.0.5
然后运行 flutter pub get 安装依赖。
使用方法
1. 设置主题颜色
可以通过调用 MediaSelector.color() 方法来设置主题颜色。
MediaSelector.color('#449897'); // 设置主题颜色为 #449897
2. 预览所选图片
通过调用 MediaSelector.previewPicture() 方法来预览所选图片。
MediaSelector.previewPicture();
3. 预览视频
通过调用 MediaSelector.previewVideo() 方法来预览所选视频。
MediaSelector.previewVideo();
4. 选择视频
通过调用 MediaSelector.select() 方法并指定类型为视频来选择视频。
var selectedVideos = await MediaSelector.select(type: PictureMimeType.ofVideo);
5. 选择图片
通过调用 MediaSelector.select() 方法并指定类型为图片来选择图片。可以限制最大选择数量,并启用压缩功能。
var selectedImages = await MediaSelector.select(
  type: PictureMimeType.ofImage,
  max: 5, // 最大选择数量
  compress: true, // 启用压缩
);
完整示例代码
以下是完整的示例代码,展示如何使用 media_selector_null_safety 插件。
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:media_selector_null_safety/media_selector.dart';
import 'package:video_thumbnail/video_thumbnail.dart';
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}
class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);
  [@override](/user/override)
  _MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
  String? path; // 视频路径
  Uint8List? uint8List; // 视频缩略图
  int max = 5; // 最大选择数量
  List<Media> list = []; // 图片列表
  List<String> selectList = []; // 已选图片路径列表
  [@override](/user/override)
  void initState() {
    // 设置主题颜色
    MediaSelector.color('#449897');
    super.initState();
  }
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('图片选择器'),
        ),
        body: GridView.builder(
          padding: const EdgeInsets.symmetric(horizontal: 15),
          gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 4,
            mainAxisSpacing: 10,
            crossAxisSpacing: 10,
            childAspectRatio: 1,
          ),
          itemCount: list.length < max ? list.length + 2 : max + 1,
          itemBuilder: (context, index) {
            // 添加视频按钮
            if (index == 0) {
              return SizedBox(
                width: 78,
                height: 78,
                child: Stack(
                  children: [
                    Align(
                      alignment: Alignment.bottomLeft,
                      child: uint8List == null
                          ? GestureDetector(
                              behavior: HitTestBehavior.opaque,
                              child: Container(
                                decoration: BoxDecoration(
                                  border: Border.all(color: const Color(0xFFDCDCDC)),
                                  borderRadius: BorderRadius.circular(4),
                                ),
                                width: 70,
                                height: 70,
                                child: Column(
                                  children: [
                                    const SizedBox(height: 8),
                                    Image.asset('images/media_video.png', width: 30, height: 30),
                                    const Text('添加视频', style: TextStyle(color: Color(0xFFBDBDBD), fontSize: 12)),
                                  ],
                                ),
                              ),
                              onTap: selectVideo,
                            )
                          : GestureDetector(
                              behavior: HitTestBehavior.opaque,
                              child: SizedBox(
                                width: 70,
                                height: 70,
                                child: Stack(
                                  children: [
                                    Image.memory(uint8List!, width: 70, height: 70, fit: BoxFit.cover),
                                    Container(
                                      alignment: Alignment.center,
                                      color: Colors.black.withOpacity(0.38),
                                      child: Image.asset('images/media_play.png', width: 22, height: 22),
                                    ),
                                  ],
                                ),
                              ),
                              onTap: () => MediaSelector.previewVideo(path),
                            ),
                    ),
                    Visibility(
                      visible: uint8List != null,
                      child: Align(
                        alignment: Alignment.topRight,
                        child: GestureDetector(
                          behavior: HitTestBehavior.opaque,
                          child: Image.asset('images/media_delete.png', width: 20, height: 20),
                          onTap: () {
                            setState(() {
                              path = null;
                              uint8List = null;
                            });
                          },
                        ),
                      ),
                    ),
                  ],
                ),
              );
            }
            // 添加图片按钮
            if (list.length < max && index == list.length + 1) {
              return SizedBox(
                width: 78,
                height: 78,
                child: Stack(
                  children: [
                    Align(
                      alignment: Alignment.bottomLeft,
                      child: GestureDetector(
                        behavior: HitTestBehavior.opaque,
                        child: Container(
                          decoration: BoxDecoration(
                            border: Border.all(color: const Color(0xFFDCDCDC)),
                            borderRadius: BorderRadius.circular(4),
                          ),
                          width: 70,
                          height: 70,
                          child: Column(
                            children: [
                              const SizedBox(height: 8),
                              Image.asset('images/media_picture.png', width: 30, height: 30),
                              Text(list.isEmpty ? '选择图片' : '${list.length} / $max', style: const TextStyle(color: Color(0xFFBDBDBD), fontSize: 12)),
                            ],
                          ),
                        ),
                        onTap: selectPictures,
                      ),
                    ),
                  ],
                ),
              );
            }
            // 显示已选图片
            return SizedBox(
              width: 78,
              height: 78,
              child: Stack(
                children: [
                  Align(
                    alignment: Alignment.bottomLeft,
                    child: GestureDetector(
                      child: Image.file(File(list[index - 1].compressPath!), width: 70, height: 70, fit: BoxFit.cover),
                      onTap: () => MediaSelector.previewPicture(selectList, index - 1),
                    ),
                  ),
                  Align(
                    alignment: Alignment.topRight,
                    child: GestureDetector(
                      child: Image.asset('images/media_delete.png', width: 20, height: 20),
                      onTap: () {
                        setState(() {
                          list.removeAt(index - 1);
                          selectList.removeAt(index - 1);
                        });
                      },
                    ),
                  ),
                ],
              ),
            );
          },
        ),
      ),
    );
  }
  // 选择视频
  selectVideo() async {
    var videos = await MediaSelector.select(type: PictureMimeType.ofVideo);
    path = videos[0].path;
    uint8List = await VideoThumbnail.thumbnailData(
      video: path!,
      imageFormat: ImageFormat.PNG,
      maxWidth: 210,
      quality: 50,
    );
    setState(() {});
  }
  // 选择图片
  selectPictures() {
    MediaSelector.select(
      type: PictureMimeType.ofImage,
      max: max,
      compress: true,
      selectList: selectList,
    ).then((value) {
      list.clear();
      selectList.clear();
      list.addAll(value);
      for (Media media in list) {
        selectList.add(media.compressPath!);
      }
      setState(() {});
    });
  }
}
更多关于Flutter媒体选择器插件media_selector_null_safety的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter媒体选择器插件media_selector_null_safety的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
media_selector_null_safety 是一个 Flutter 插件,用于从设备中选择媒体文件(如图片和视频)。它是 media_selector 插件的空安全版本,适用于 Flutter 2.0 及以上版本,支持空安全特性。
安装插件
首先,在 pubspec.yaml 文件中添加 media_selector_null_safety 插件的依赖:
dependencies:
  flutter:
    sdk: flutter
  media_selector_null_safety: ^1.0.0  # 请使用最新版本
然后,运行 flutter pub get 来安装插件。
使用插件
1. 导入插件
在 Dart 文件中导入插件:
import 'package:media_selector_null_safety/media_selector_null_safety.dart';
2. 选择图片或视频
使用 MediaSelector 类来打开设备中的图片或视频选择器。
class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  String? _selectedMediaPath;
  Future<void> _pickMedia() async {
    // 选择图片或视频
    final String? result = await MediaSelector.selectMedia(
      context: context,
      mediaType: MediaType.image, // 或 MediaType.video
    );
    setState(() {
      _selectedMediaPath = result;
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Media Selector Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            _selectedMediaPath != null
                ? Image.file(File(_selectedMediaPath!)) // 显示选择的图片
                : Text('No media selected'),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _pickMedia,
              child: Text('Pick Media'),
            ),
          ],
        ),
      ),
    );
  }
}
3. 处理权限
在 Android 和 iOS 上,访问媒体文件需要相应的权限。确保在 AndroidManifest.xml 和 Info.plist 中添加必要的权限。
Android:
在 android/app/src/main/AndroidManifest.xml 中添加以下权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
iOS:
在 ios/Runner/Info.plist 中添加以下键值对:
<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to your photo library to select media.</string>
其他功能
media_selector_null_safety 还支持其他功能,例如:
- 多选媒体文件:通过设置 
allowMultiple参数为true,可以允许用户选择多个媒体文件。 - 自定义媒体类型:通过 
MediaType枚举,可以选择图片、视频或两者。 
final List<String>? result = await MediaSelector.selectMedia(
  context: context,
  mediaType: MediaType.image,
  allowMultiple: true,
);
        
      
            
            
            
