Flutter 相册图片多选(flutter 图表)
前一段项目要做类似微信朋友圈的评论回复功能,要多选图片,当时在网上也找了一下,发现文章并不是太多,就把自己写的也记录一下(主要是我们的项目使用的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
及以上相册打不开,你需要修改你项目中的这个地方,上图:
这里就是去除安卓11的新特性,可以使插件正常使用。
以上就是这篇文章的全部内容了,写的不好的地方还请多多指教!
伪原创工具 SEO网站优化 https://www.237it.com/
作者:小手捶大手
链接:https://juejin.cn/post/7035904267240095757