美文网首页
Flutter 相册图片多选

Flutter 相册图片多选

作者: 瞬间完善 | 来源:发表于2021-06-01 14:03 被阅读0次

    前一段项目要做类似微信朋友圈的评论回复功能,要多选图片,当时在网上也找了一下,发现文章并不是太多,就把自己写的也记录一下(主要是我们的项目使用的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:https://baike.baidu.com/item/HEIC/10444257
    jpg: https://baike.baidu.com/item/JPEG%E6%A0%BC%E5%BC%8F/3462770
    HEIF & HEVC https://juejin.im/post/59ddc13ff265da432319f438

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

    image.png
    这里就是去除安卓11的新特性,可以使插件正常使用。

    以上就是这篇文章的全部内容了,写的不好的地方还请多多指教!

    相关文章

      网友评论

          本文标题:Flutter 相册图片多选

          本文链接:https://www.haomeiwen.com/subject/eypwsltx.html