Hellom's Studio.

flutter 之 拍照及本地相册获取图片

字数统计: 693阅读时长: 3 min
2019/08/09 Share

app 大部分应用都会调用本地相机 拍照等功能

那么在 flutter 里如何操作呢?

flutter 需要用到 image_picker 这个插件来获取图像

https://pub.dev/packages/image_picker#-readme-tab-

配置

首先 需要在 pubspec.yaml 文件中 添加 image_picker

dependencies:
    flutter:
       sdk: flutter

# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
url_launcher: ^5.1.1

image_picker: ^0.6.1   <== 添加插件

IOS

IOS 需要配置一些访问使用的说明

找到 /ios/Runner/Info.plist 文件 添加如下字段

<key>NSCameraUsageDescription</key>
<string>在这里配置相机使用说明</string>
<key>NSMicrophoneUsageDescription</key>
<string>在这里配置录音使用说明</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>在这里配置相册的使用说明</string>

Android

无需配置 但是 image_picker 是基于 Android X 所以需要兼容 Android X

根据下面的网址中 更改 Android 的一些配置文件

https://flutter.dev/docs/development/packages-and-plugins/androidx-compatibility

相关报错问题

关于 Android模拟器调用相册功能报错

本以为是配置文件 少配置了什么 检查了各种配置 还以为是版本不兼容什么问题

找了很多资料 依旧都是报错 比较烦躁

后面查到说 flutter clean 就行了 抱着将信将疑的态度试下了 结果好了

心情极其复杂 果然多踩坑 才能进步 [○・`Д´・ ○] [○・`Д´・ ○]

实例

关于运行后报错 ‘The method ‘map’ was called on null.’ 的问题

定义的 _images 需要初始化 List<File> _images = [];

以下是具体代码:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
e.g.

import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:io';

class PhotoApp extends StatefulWidget {
@override
_PhotoAppState createState() => _PhotoAppState();
}

class _PhotoAppState extends State<PhotoApp> {
List<File> _images = [];

Future getImage(isTakePhoto) async {

Navigator.pop(context); // 选完图片后 关闭底部弹框

var image = await ImagePicker.pickImage(
source: isTakePhoto ? ImageSource.camera : ImageSource.gallery);

setState(() {
_images.add(image);
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('拍照APP开发'),
),
body: Center(
child: Wrap(
spacing: 5,
runSpacing: 5,
children: _getImages(),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _pickImage,
tooltip: '选择图片',
child: Icon(Icons.add_a_photo),
),
);
}

// 底部弹框
_pickImage() {
showModalBottomSheet(
context: context,
builder: (context) => Container(
height: 160,
child: Column(
children: <Widget>[
_item('拍照', true),
_item('从相册选择', false),
],
),
));
}

// 底部弹框 显示列表内容
_item(String title, bool isTakePhoto) {
return GestureDetector(
// 卡片列表控件
child: ListTile(
leading: Icon(isTakePhoto ? Icons.camera_alt : Icons.photo_library),
title: Text(title),
onTap: () => getImage(isTakePhoto),
),
);
}

// 获取图片
_getImages() {
return _images.map((file) {
return Stack(
children: <Widget>[
ClipRRect(
// 圆角效果
borderRadius: BorderRadius.circular(5),
child: Image.file(
file,
width: 120,
height: 90,
fit: BoxFit.fill,
),
),
Positioned(
right: 5,
top: 5,
child: ClipOval(
// 圆角删除按钮
child: GestureDetector(
onTap: () {
setState(() {
_images.remove(file);
});
},
child: ClipOval(
child: Container(
padding: EdgeInsets.all(3),
decoration: BoxDecoration(color: Colors.black54),
child: Icon(
Icons.close,
color: Colors.white,
size: 18,
),
),
),
)),
)
],
);
}).toList(); // map 转换为 list
}
}
CATALOG
  1. 1. 配置
  2. 2. IOS
  3. 3. Android
  4. 4. 相关报错问题
    1. 4.1. 关于 Android模拟器调用相册功能报错
  5. 5. 实例
    1. 5.1. 关于运行后报错 ‘The method ‘map’ was called on null.’ 的问题