Flutter图片选择插件image_pickers的使用

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

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

1 回复

更多关于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.xmlInfo.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'),
            ),
          ],
        ),
      ),
    );
  }
}

说明

  1. 依赖添加:在pubspec.yaml中添加image_picker依赖。
  2. 状态管理:使用StatefulWidget来管理图片文件的状态。
  3. 选择图片:定义_pickImage方法,它接受一个ImageSource枚举(gallerycamera),并调用_picker.pickImage方法来选择图片。
  4. 显示图片:如果选择了图片,使用Image.file来显示图片。
  5. 按钮:提供两个按钮,一个用于从图库中选择图片,另一个用于从相机中选择图片。

确保在实际部署到iOS或Android设备之前,根据平台要求配置必要的权限和设置。对于iOS,你需要在Info.plist中添加相机和照片库的权限请求。对于Android,你需要在AndroidManifest.xml中声明这些权限,并可能需要在运行时请求它们(尽管image_picker插件已经为你处理了大部分逻辑)。

回到顶部