flutter实现多图选择+常用做法
2021-03-30 本文已影响0人
_诸葛青
先看效果。
1617074157230.gif
注:可以用其他多图片选择插件,列表插件可以不用。
#图片选择
wechat_assets_picker: ^4.2.1
#列表
flutter_staggered_grid_view: ^0.3.2
Android配置
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
361617070061_.pic_hd.jpg
完整代码
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
class PhotoTool extends StatefulWidget {
@required final int imageCount;//最多几张
@required final int lineCount;//一行几个
//注:最好把图片和文字这些都拿出来,方便更改,这里就不搞了
const PhotoTool({Key key, this.imageCount,this.lineCount});
@override
_PhotoToolState createState() => _PhotoToolState();
}
class _PhotoToolState extends State<PhotoTool> {
List<AssetEntity> _imageFiles = [];
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
text: '说明:',
style: Theme.of(context).textTheme.subtitle2,
children: [
TextSpan(
text: '(说明:上传图片,最多${widget.imageCount}张)',
style: Theme.of(context)
.textTheme
.bodyText2
.copyWith(color: Colors.grey),
),
],
),
),
SizedBox(height: 16.0),
StaggeredGridView.countBuilder(
shrinkWrap: true,
crossAxisCount: widget.lineCount,
itemCount: _imageFiles.length == widget.imageCount
? _imageFiles.length
: _imageFiles.length + 1,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
if (_imageFiles.length < widget.imageCount && index == 0) {
return InkWell(
onTap: () => _onPickImage(),
child: Container(
padding: EdgeInsets.all(5),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Color(0xFFF6F7F8),
),
child: Center(
child: Icon(
Icons.add,
color: Color(0xFFB4B4B4),
size: 40,
),
),
),
),
);
} else {
return Stack(
children: [
Container(
padding: EdgeInsets.all(5),
child: InkWell(
child: FutureBuilder<File>(
future: _imageFiles[
_imageFiles.length < widget.imageCount
? index - 1
: index]
.file,
builder: (context, snapshot) {
return snapshot.connectionState ==
ConnectionState.done
? Container(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius:
BorderRadius.circular(6.0),
image: DecorationImage(
image: FileImage(snapshot.data),
fit: BoxFit.cover,
),
),
)
: Container(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius:
BorderRadius.circular(6.0),
color: Color(0xFFF6F7F8),
),
child: Center(
child: CupertinoActivityIndicator(),
),
);
},
),
),
),
InkWell(
onTap: () => _deleteImage(
_imageFiles.length < widget.imageCount
? index - 1
: index),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(99.0),
color: Colors.red,
),
padding: EdgeInsets.all(2.0),
child: Icon(
Icons.close,
size: 20.0,
color: Colors.white,
),
),
),
],
);
}
},
staggeredTileBuilder: (int index) =>
new StaggeredTile.count(1, 1),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
),
],
),
),
);
}
/// 选择图片
_onPickImage() async {
List<AssetEntity> assets = await AssetPicker.pickAssets(
context,
maxAssets: widget.imageCount - _imageFiles.length,
themeColor: Theme.of(context).primaryColor,
requestType: RequestType.image,
);
if (assets == null || assets.length <= 0) return;
setState(() {
_imageFiles.addAll(assets);
});
}
/// 删除图片
_deleteImage(int index) {
if (_imageFiles == null || _imageFiles.length <= index) return;
setState(() {
_imageFiles.removeAt(index);
});
}
}
使用
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body:PhotoTool(
imageCount: 9,
lineCount: 3,
)
其他说明(可能用到):正常我们对接接口都是给接口传base64.格式
///AssetEntity转Fil .file(插件自带)
///file转base64
//通过图片路径将图片转换成Base64字符串
Future image2Base64(String path) async {
File file = new File(path);
List<int> imageBytes = await file.readAsBytes();
return base64Encode(imageBytes);
}
///基本用法
_imageFiles.forEach((item) {
item.file.then((value)async{
String _base64ImageStr = await CommonUtils.getInstance().image2Base64(value.path);
});
});