前言
虽然现在Flutter关于裁剪图片的插件挺多,在经过一下午的踩坑后,发现了其中很多问题,在Pub上排名靠前的两个插件均有问题
image_crop
问题是在于如果不嵌套在MaterilaApp当中,选择图片后,无法正常裁剪,而且会将原图片损坏,导致原图片也无法使用,真的恶心
simple_image_crop
是因为由于近期刚更新了版本,我在下载了示例代码后,运行时直接报错,希望作者在之后能够修改一个这个Bug问题。
正文
接下来就进入正题了,给大家介绍亲测好用的插件image_cropper
,首先给大家展示一下我使用的效果
Pub地址
:https://pub.dev/packages/image_cropper
注意:
该插件是配合着image_picker
插件来使用的,image_picker是用来呼唤起用户的相机以及选择图片用的,具体可以去参考官方文档https://pub.dev/packages/image_picker
这个是我自己封装好的插件,只是把调用摄像头和裁剪的方法封装进去了,方便别的页面调用
import 'package:project/plugins/Plugins.dart';
这个是我封装的屏幕适配类,具体可参考我的另外一篇文章:https://blog.csdn.net/qq_38774121/article/details/102883746
import 'package:project/plugins/ScreenAdapter.dart';
这个是我封装的统一请求接口类,用来发送上传图片请求的,具体可参考我的另外一篇文章:https://blog.csdn.net/qq_38774121/article/details/102883746
import 'package:project/config/api.dart';
完整代码
(具体的意思我全部写在代码当中了,如果有什么问题,请留言给我,24小时内答复您)
import 'dart:convert';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:project/plugins/Plugins.dart';
import 'package:project/plugins/ScreenAdapter.dart';
import 'package:project/config/api.dart';
class ModifyUserInfo extends StatefulWidget {
@override
_ModifyUserInfoState createState() => _ModifyUserInfoState();
}
class _ModifyUserInfoState extends State<ModifyUserInfo> {
File _file;
var _croppFile;
var api = Api();
var imageUrl = 'https://huyaimg.msstatic.com/avatar/1084/37/7c96090110880e88916b11e4a18cf9_180_135.jpg?437764'; // 初始化默认图片
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Container(
child: Text('测试页面'),
),
),
body: ConstrainedBox(
constraints: BoxConstraints.expand(),
child: Container(
color: Color.fromRGBO(233, 233, 233, 0.7),
child: ListView(
children: <Widget>[
InkWell(
child: Container(
padding: EdgeInsets.symmetric(
horizontal: ScreenAdapter.setWidth(20)),
color: Colors.white,
height: ScreenAdapter.setHeight(150),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'头像',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: ScreenAdapter.size(28)),
),
Row(
children: <Widget>[
CircleAvatar(
backgroundImage: NetworkImage(imageUrl),
radius: 40.0,
),
Icon(Icons.chevron_right)
],
),
],
),
),
onTap: showSelectPicker,
),
UserInfoList('昵称', '磐石Boy'),
// Text('')
_croppFile != null ? Image.file(_croppFile) : Text('')
],
),
),
));
}
// 选择图片
showSelectPicker() {
showModalBottomSheet(
context: context,
builder: (context){
return Container(
height: ScreenAdapter.setHeight(200),
child: Column(
children: <Widget>[
InkWell(
onTap: () async {
var file = await Plugins.takePhoto();
if(file!=null){
// 获取图片路径
setState(() {
_file = file;
});
// 关闭弹窗
Navigator.pop(context);
// 获取裁剪后地址
var croppFile = await Plugins.cropImage(context, file.path);
// 请求接口上传图片
if(croppFile!=null){
api.postData('uploadFile', formData: await FormData1(croppFile.path)).then((val){
var imgurl = json.decode(val.toString());
setState(() {
imageUrl = 'https://flutter.ikuer.cn/'+imgurl['file_path'];
});
});
setState(() {
_croppFile = croppFile;
});
}
}
},
child: Container(
alignment: Alignment.center,
height: ScreenAdapter.setHeight(100),
child: Text('拍照'),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 0.5,
color: Colors.black26
)
)
),
),
),
InkWell(
onTap: () async {
var file = await Plugins.openGallery();
if(file!=null){
setState(() {
_file = file;
});
Navigator.pop(context);
var croppFile = await Plugins.cropImage(context, file.path);
if(croppFile!=null){
api.postData('uploadFile', formData: await FormData1(croppFile.path)).then((val){
var imgurl = json.decode(val.toString());
setState(() {
imageUrl = 'https://flutter.ikuer.cn/'+imgurl['file_path'];
});
});
setState(() {
_croppFile = croppFile;
});
}
}
},
child: Container(
alignment: Alignment.center,
height: ScreenAdapter.setHeight(100),
child: Text('相册选择'),
),
)
],
)
);
}
);
}
// dio上传文件FormData格式
Future<FormData> FormData1(fileUrl) async {
return FormData.fromMap({
"file": await MultipartFile.fromFile(fileUrl)
});
}
// 用户信息列表
Widget UserInfoList(String title, String subtitle) {
return Container(
padding: EdgeInsets.symmetric(horizontal: ScreenAdapter.setWidth(20)),
color: Colors.white,
height: ScreenAdapter.setHeight(150),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'${title}',
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: ScreenAdapter.size(28)),
),
Row(
children: <Widget>[Text('${subtitle}'), Icon(Icons.chevron_right)],
)
],
),
);
}
}