Flutter媒体选择器插件media_selector_null_safety的使用

发布于 1周前 作者 zlyuanteng 来自 Flutter

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

1 回复

更多关于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.xmlInfo.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,
);
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!