Flutter-ImagePicker-ImageCropper

ImagePicker

Flutter用于选择图片的工具包。

依赖引入

1
image_picker: ^0.8.6

使用

1
2
3
4
5
final ImagePicker _picker=ImagePicker();//创建选择器实例
onPressed: ()async{
//从相册选择图片
final image=await _picker.pickImage(source: ImageSource.gallery);
}

ImageCropper

用于图片裁剪的工具包

依赖引入

1
image_cropper: ^3.0.0

相关配置(安卓需要配置,ios不需要)

在AndroidManifest.xml加入以下信息。

1
2
3
4
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>

使用

1
CroppedFile? croppedImage=await ImageCropper().cropImage(sourcePath: image.path);//创建裁剪器给定图片源进行裁剪

两者结合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Widget build(BuildContext context) {
//创建图片选择器实例
final ImagePicker _picker=ImagePicker();
return ElevatedButton(
//单击按钮触发选择
onPressed: ()async{
//从相册选择图片
final image=await _picker.pickImage(source: ImageSource.gallery); //返回的是XFile对象
//选择了图片则创建裁剪器实例进入裁剪环节
if(image!=null){
CroppedFile? croppedImage=await ImageCropper().cropImage(sourcePath: image.path);//根据XFile对象的路径获得图片进行裁剪
//裁剪了则把裁剪后的图片设置为预览的文件源
if(croppedImage!=null){
context.read<ImageData>().setImage(File(croppedImage.path));//CroppedFile转File,上传图片的时候根据File转MultipartFile即可
}
//未裁剪则设置裁剪之前选择的图片作为预览的文件源
else{
context.read<ImageData>().setImage(File(image.path));
}
}
},
style: ButtonStyle(
shape: MaterialStateProperty.all(const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(30))
)),
//设置按钮宽度高度等
minimumSize: MaterialStateProperty.all(const Size(300, 40)),
backgroundColor: MaterialStateProperty.all(MyColors.rgbRed)
),
child: const Text("Select a photo from gallery"),
);
}

图片上传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//图片选择或裁剪完毕后,单击完成上传
class FinishedButton extends StatelessWidget {
const FinishedButton({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
//创建dio实例,用于发送http请求
final dio=Dio();
//获取已经准备好的图片文件源
File? image=context.watch<ImageData>().image;
return ElevatedButton(
onPressed: image==null?//没有文件源代表没有选图片,不进行上传操作
(){}://有文件源就进入上传阶段
()async{
final multipartImg=await MultipartFile.fromFile(image.path);//根据文件源生成媒体图片
final map=<String,dynamic>{};//创建map存储图片
map['file']=await MultipartFile.fromFile(image.path);
//将map转为表单数据后,发送post请求,上传服务器,并接收返回的数据
var response=await dio.post("$serviceUploadHeader/${context.read<UserMsg>().userId}",data: FormData.fromMap(map));
context.read<UserMsg>().setHeadImg(response.data);//及时更新头像的链接
Navigator.pop(context);//上传完毕即退回首页
},
style: ButtonStyle(
backgroundColor: image==null?
MaterialStateProperty.all(Colors.grey):
MaterialStateProperty.all(MyColors.rgbRed)
),
child: const Text("Finished",),
);
}
}