前一段项目要做类似微信朋友圈的谈论回复功用,要多选图片,当时在网上也找了一下,发现文章并不是太多,就把自己写的也记录一下(主要是咱们的项目使用的flutter版别太低了1.17.2的,flutter2.0.1版别之上可使用images_picker插件,一个插件满足您的需求)。 ###插件

dependencies:
  photo:
    path: ./flutter_photo #这个插件pub_dev上也不是最新的,我是把作者发布到git上的拉下来导入到项目中了
  image_picker: ^0.6.7+22

为什么要用两个插件,是因为image_picker 这个插件尽管支撑摄影和相册挑选,可是图片只能一张一张的挑选,photo 是支撑图片多选的(可是这个插件好久没更新了)

废话不多说,开始上代码:

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_app_image_picker/photo_picker_tool.dart';
void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar:AppBar(
            title:Text('PhotoSelectTest')
        ),
        body:
        Container(
            padding: EdgeInsets.fromLTRB(80, 10, 30, 10),
            color: Colors.red,
            child:
            JhPhotoPickerTool(
              lfPaddingSpace: 110,
              callBack: (var img) async{
                print("img-------${File(img[0]).lengthSync()}------");
                print(img.length);
                print(img);
              },
            )
        )
    );
  }
}
import 'package:flutter/material.dart';
import 'package:jxcapp/utils/image_utils.dart';
import 'package:photo/photo.dart';
import 'package:photo_manager/photo_manager.dart';
import 'dart:io';
import 'package:image_picker/image_picker.dart';
import 'package:heic_to_jpg/heic_to_jpg.dart';
const double itemSpace = 10.0;
const double space = 5.0; //上下左右距离
const double deleBtnWH = 20.0;
const Color bgColor = Colors.white;
const int maxCount = 3;// 最大挑选图片数量
typedef CallBack = void Function(List imgData);
class JhPhotoPickerTool extends StatefulWidget {
  final double lfPaddingSpace; //外部设置的左右距离
  final CallBack callBack;
  JhPhotoPickerTool({
    this.lfPaddingSpace,
    this.callBack,
  });
  @override
  _JhPhotoPickerToolState createState() => _JhPhotoPickerToolState();
}
class _JhPhotoPickerToolState extends State<JhPhotoPickerTool> {
  List _imgData = List(); //图片list
  List imgDefaultData = List(); //图片list
  List<AssetEntity> imgPicked = [];
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    imgDefaultData.add("selectPhoto_add"); //先增加 加号按钮 的图片
  }
  @override
  void setState(fn) {
    // TODO: implement setState
    super.setState(fn);
    List data = List();
    data.addAll(_imgData);
    // data.removeAt(_imgData.length - 1);
    widget.callBack(data);
  }
  @override
  Widget build(BuildContext context) {
    var kScreenWidth = MediaQuery.of(context).size.width;
    var lfPadding = widget.lfPaddingSpace == null ? 0.0 : widget.lfPaddingSpace;
    var ninePictureW = (kScreenWidth - space * 2 - 2 * itemSpace - lfPadding);
    var itemWH = ninePictureW / maxCount;
    int columnCount = _imgData.length > 6 ? 3 : _imgData.length <= 3 ? 1 : 2;
    return Container(
        color: bgColor,
        width: kScreenWidth - lfPadding,
        height:
            columnCount * itemWH + space * 2 + (columnCount - 1) * itemSpace,
        child: GridView.builder(
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              //能够直接指定每行(列)显现多少个Item
              //一行的Widget数量
              crossAxisCount: 3,
              crossAxisSpacing: itemSpace, //水平距离
              mainAxisSpacing: itemSpace, //垂直距离
              childAspectRatio: 1.0, //子Widget宽高比例
            ),
            physics: NeverScrollableScrollPhysics(),
            padding: EdgeInsets.all(space),
            //GridView内边距
            itemCount: _imgData.length== maxCount?_imgData.length: (_imgData.length + imgDefaultData.length),
            itemBuilder: (context, index) {
              if (_imgData.length == maxCount) {
                return imgItem(index, setState, _imgData, imgPicked);
              } else {
                if (index == _imgData.length) {
                  return addBtn(context, setState, imgDefaultData, imgPicked);
                } else {
                  return imgItem(index, setState, _imgData, imgPicked);
                }
              }
            }));
  }
  /** 增加按钮 */
  Widget addBtn(context, setState, imgData, imgPicked) {
    return GestureDetector(
      child: Container(
        color: Color(0xffF7F7F7),
        padding: EdgeInsets.all(40),
        child: Image.asset(
          ImageUtils.getImgPath('report/report_add_icon'),
          // fit: BoxFit.cover,
        ),
      ),
      onTap: () {
        FocusScope.of(context).requestFocus(FocusNode());
        showModalBottomSheet(
          context: context,
          builder: (BuildContext context) {
            return new Container(
              height: 195.0,
              child: Column(
                children: <Widget>[
                  MaterialButton(
                    height:50,
                    child: Text('拍摄'),
                    onPressed: () async {
                      Navigator.pop(context);
                      var image = await ImagePicker.pickImage(
                          source: ImageSource.camera);
                      print(image);
                      if(image.absolute.path.contains('.he') || image.absolute.path.contains('.HE')){
                        String jpegPath = await HeicToJpg.convert(image.absolute.path);
                        _imgData.insert(_imgData.length, jpegPath);
                      }
                      else{
                        _imgData.insert(_imgData.length, image.absolute.path);
                      }
                      // _imgPicked.add(image);
                      setState(() {});
                    },
                  ),
                  SizedBox(
                    height: 1,
                    child: Container(
                      color: Color(0xffF4F4F4),
                    ),
                  ),
                  MaterialButton(
                    height:50,
                    child: Text('从手机相册挑选'),
                    onPressed: () async {
                      pickAsset(context, setState, _imgData, imgPicked);
                      Navigator.pop(context);
                    },
                  ),
                  SizedBox(
                    height: 10,
                    child: Container(
                      color: Color(0xffF4F4F4),
                    ),
                  ),
                  MaterialButton(
                    height:50,
                    child: Text('取消'),
                    onPressed: () {
                      Navigator.pop(context);
                    },
                  ),
                ],
              ),
            );
          },
        ).then((val) {
          print(val);
        });
      },
    );
  }
  /** 多图挑选 */
  void pickAsset(context, setState, imgData, imgPicked) async {
    final result = await PhotoPicker.pickAsset(
        context: context,
        pickedAssetList: imgPicked,
        maxSelected: maxCount - _imgData.length,
        pickType: PickType.onlyImage);
    if (result != null && result.isNotEmpty) {
      for (var e in result) {
        var file = await e.file;
//         if (!imgData.contains(file.absolute.path)) {// 如果想防止重复选同一张图片,能够加上这个判断
        if(file.absolute.path.contains('.he') || file.absolute.path.contains('.HE')){// 这个判断的含义请持续往下看
          String jpegPath = await HeicToJpg.convert(file.absolute.path);
          _imgData.insert(_imgData.length, jpegPath);
        }
        else{
          _imgData.insert(_imgData.length, file.absolute.path);
        }
        // }
      }
    }
    setState(() {});
  }
  /** 图片和删去按钮 */
  Widget imgItem(index, setState, imgData, imgPicked) {
    return GestureDetector(
      child: Container(
        color: Colors.transparent,
        child: Stack(alignment: Alignment.topRight, children: <Widget>[
          ConstrainedBox(
            child: Image.file(File(imgData[index]), fit: BoxFit.cover),
            constraints: BoxConstraints.expand(),
          ),
          GestureDetector(
            child: Image.asset(
              ImageUtils.getImgPath('report/report_delete'),//这是我本地的增加图片
              // fit: BoxFit.cover,
            ),
            onTap: () {
              //点击删去按钮
              setState(() {
                _imgData.removeAt(index);
                // imgPicked.removeAt(index);
              });
            },
          )
        ]),
      ),
      onTap: () {
        print("点击第${index}张图片");
      },
    );
  }
}

以上便是我的代码,可能有的朋友就问了heic_to_jpg 这个插件是干什么用的, 苹果heic格局图片不能直接在浏览器上显现,所以咱们就需要借用插件转换一下格局,详细请看:

heic:baike.baidu.com/item/HEIC/1… jpg:baike.baidu.com/item/JPEG%E… HEIF & HEVC juejin.im/post/59ddc1…

到这里还不算结束,安卓还有一个问题,便是体系是安卓11及以上相册打不开,你需要修正你项目中的这个当地,上图:

Flutter 相册图片多选
这里便是去除安卓11的新特性,能够使插件正常使用。

以上便是这篇文章的全部内容了,写的欠好的当地还请多多指教!