前一段項目要做類似微信朋友圈的評論回復(fù)功能垦细,要多選圖片捺典,當(dāng)時在網(wǎng)上也找了一下浅碾,發(fā)現(xiàn)文章并不是太多大州,就把自己寫的也記錄一下(主要是我們的項目使用的flutter版本太低了1.17.2的,flutter2.0.1版本之上可使用images_picker
插件,一個插件滿足您的需求)垂谢。
插件
dependencies:
photo:
path: ./flutter_photo #這個插件pub_dev上也不是最新的厦画,我是把作者發(fā)布到git上的拉下來導(dǎo)入到項目中了
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;// 最大選擇圖片數(shù)量
typedef CallBack = void Function(List imgData);
class JhPhotoPickerTool extends StatefulWidget {
final double lfPaddingSpace; //外部設(shè)置的左右間距
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數(shù)量
crossAxisCount: 3,
crossAxisSpacing: itemSpace, //水平間距
mainAxisSpacing: itemSpace, //垂直間距
childAspectRatio: 1.0, //子Widget寬高比例
),
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.all(space),
//GridView內(nèi)邊距
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)) {// 如果想避免重復(fù)選同一張圖片徙邻,可以加上這個判斷
if(file.absolute.path.contains('.he') || file.absolute.path.contains('.HE')){// 這個判斷的意義請繼續(xù)往下看
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格式圖片不能直接在瀏覽器上顯示缰犁,所以我們就需要借用插件轉(zhuǎn)換一下格式淳地,詳細請看:
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
到這里還不算結(jié)束怖糊,安卓還有一個問題,就是系統(tǒng)是安卓11
及以上相冊打不開颇象,你需要修改你項目中的這個地方伍伤,上圖:
這里就是去除安卓11的新特性,可以使插件正常使用遣钳。
以上就是這篇文章的全部內(nèi)容了扰魂,寫的不好的地方還請多多指教!