image_picker를 사용하면 간단하게 기기에서 사진 파일을 가져올 수 있습니다
image_picker를 사용해서 사진을 업로드하는 화면을 구현해보겠습니다
1. image_picker를 설치
Pubspec.yaml 파일 dependencies: 에서 image_picker: ^0.8.7 플러그인 추가
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
image_picker: ^0.8.7
추가하고 Pub get을 눌러주세요
2. ios > Runner > Info.plist 파일에 아래 코드를 추가해주세요.
<key>NSCameraUsageDescription</key>
<string>카메라 사용에 필요합니다.</string>
<key>NSMicrophoneUsageDescription</key>
<string>마이크 사용에 필요합니다.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>사진 라이브러리 사용에 필요합니다.</string>
<key>UILaunchStoryboardName</key>
ios > Runner > Info.plist
<?xml version="1.0" encoding="UTF-8"?>
http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
.
.
.
// 추가
<key>NSCameraUsageDescription</key>
<string>카메라 사용에 필요합니다.</string>
<key>NSMicrophoneUsageDescription</key>
<string>마이크 사용에 필요합니다.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>사진 라이브러리 사용에 필요합니다.</string>
<key>UILaunchStoryboardName</key>
.
.
.
</dict>
</plist>
안드로이드에서는 별도의 설정을 하실 필요가 없습니다.
3. 화면을 만들 페이지에서 아래 내용을 import 해주세요
import 'dart:io';
import 'package:image_picker/image_picker.dart';
4. StatefulWidget으로 페이지를 만들고 아래 변수들을 선언해주세요
final picker = ImagePicker();
XFile? image; // 카메라로 촬영한 이미지를 저장할 변수
List<XFile?> multiImage = []; // 갤러리에서 여러 장의 사진을 선택해서 저장할 변수
List<XFile?> images = []; // 가져온 사진들을 보여주기 위한 변수
5. 아이콘 버튼 2개를 만들어줍니다(카메라로 촬영하기, 갤러리에서 가져오기)
//카메라로 촬영하기
Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(5),
decoration: BoxDecoration(color: Colors.lightBlueAccent, borderRadius: BorderRadius.circular(5),
boxShadow: [
BoxShadow(color: Colors.grey.withOpacity(0.5), spreadRadius: 0.5, blurRadius: 5)
],
),
child: IconButton(
onPressed: () async {
image = await picker.pickImage(source: ImageSource.camera);
//카메라로 촬영하지 않고 뒤로가기 버튼을 누를 경우, null값이 저장되므로 if문을 통해 null이 아닐 경우에만 images변수로 저장하도록 합니다
if (image != null) {
setState(() {
images.add(image);
});
}
},
icon: Icon(Icons.add_a_photo, size: 30, color: Colors.white,)
)
),
//갤러리에서 가져오기
Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(5),
decoration: BoxDecoration(color: Colors.lightBlueAccent, borderRadius: BorderRadius.circular(5),
boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.5), spreadRadius: 0.5, blurRadius: 5)],
),
child: IconButton(
onPressed: () async {multiImage = await picker.pickMultiImage();
setState(() {
//multiImage를 통해 갤러리에서 가지고 온 사진들은 리스트 변수에 저장되므로 addAll()을 사용해서 images와 multiImage 리스트를 합쳐줍니다.
images.addAll(multiImage);
});
},
icon: Icon(
Icons.add_photo_alternate_outlined,
size: 30,
color: Colors.white,
)
)
),
아이콘을 클릭하면 각각 카메라 촬영화면, 갤러리로 넘어가는 것을 확인할 수 있습니다.
6. 가져온 사진 보여주기
카메라로 촬영하거나 갤러리에서 가져온 사진들을 모두 images 변수에 저장되도록 했습니다.
이제 GridView.builder 위젯을 사용해서 사진들을 그리드 모양으로 보여주도록 하겠습니다.
Container(
margin: EdgeInsets.all(10),
child: GridView.builder(padding: EdgeInsets.all(0),
shrinkWrap: true,
itemCount: images.length, //보여줄 item 개수. images 리스트 변수에 담겨있는 사진 수 만큼.
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, //1 개의 행에 보여줄 사진 개수
childAspectRatio:
1 / 1, //사진 의 가로 세로의 비율
mainAxisSpacing: 10, //수평 Padding
crossAxisSpacing: 10, //수직 Padding
),
itemBuilder: (BuildContext context, int index) {
// 사진 오른 쪽 위 삭제 버튼을 표시하기 위해 Stack을 사용함
return Stack(
alignment: Alignment.topRight,
children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
image:
DecorationImage(
fit: BoxFit.cover, //사진 크기를 Container 크기에 맞게 조절
image: FileImage(File(images[index]!.path // images 리스트 변수 안에 있는 사진들을 순서대로 표시함
))
)
),
),
Container(
decoration: BoxDecoration(
color: Colors.black,
borderRadius:
BorderRadius.circular(5),
),
//삭제 버튼
child: IconButton(
padding: EdgeInsets.zero,
constraints: BoxConstraints(),
icon: Icon(Icons.close,
color: Colors.white,
size: 15),
onPressed: () {
//버튼을 누르면 해당 이미지가 삭제됨
setState(() {
images.remove(images[index]);
});
},
)
)
],
);
},
),
),
이렇게 하면 가져온 사진들이 정상적으로 보이는 것을 확인하실 수 있습니다. 이제 버튼을 만들어서 사진들을 전송하거나 DB에 저장하는 등의 방법으로 활용하시면 되겠습니다.
※ 전체 코드
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:image_picker/image_picker.dart';
class ImageUpload extends StatefulWidget {
@override
State<ImageUpload> createState() => ImageUploadState();
}
final picker = ImagePicker();
XFile? image; // 카메라로 촬영한 이미지를 저장할 변수
List<XFile?> multiImage = []; // 갤러리에서 여러장의 사진을 선택해서 저장할 변수
List<XFile?> images = []; // 가져온 사진들을 보여주기 위한 변수
class ImageUploadState extends State<ImageUpload> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: EdgeInsets.all(10),
child: Column(
children: [
SizedBox(
height: 50,
),
Row(
children: [
//카메라로 촬영하기
Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(5),
decoration: BoxDecoration(color: Colors.lightBlueAccent, borderRadius: BorderRadius.circular(5),
boxShadow: [
BoxShadow(color: Colors.grey.withOpacity(0.5), spreadRadius: 0.5, blurRadius: 5)
],
),
child: IconButton(
onPressed: () async {
image = await picker.pickImage(source: ImageSource.camera);
//카메라로 촬영하지 않고 뒤로가기 버튼을 누를 경우, null값이 저장되므로 if문을 통해 null이 아닐 경우에만 images변수로 저장하도록 합니다
if (image != null) {
setState(() {
images.add(image);
});
}
},
icon: Icon(Icons.add_a_photo, size: 30, color: Colors.white,)
)
),
//갤러리에서 가져오기
Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(5),
decoration: BoxDecoration(color: Colors.lightBlueAccent, borderRadius: BorderRadius.circular(5),
boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.5), spreadRadius: 0.5, blurRadius: 5)],
),
child: IconButton(
onPressed: () async {multiImage = await picker.pickMultiImage();
setState(() {
//갤러리에서 가지고 온 사진들은 리스트 변수에 저장되므로 addAll()을 사용해서 images와 multiImage 리스트를 합쳐줍니다.
images.addAll(multiImage);
});
},
icon: Icon(
Icons.add_photo_alternate_outlined,
size: 30,
color: Colors.white,
)
)
),
],
),
Container(
margin: EdgeInsets.all(10),
child: GridView.builder(padding: EdgeInsets.all(0),
shrinkWrap: true,
itemCount: images.length, //보여줄 item 개수. images 리스트 변수에 담겨있는 사진 수 만큼.
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, //1 개의 행에 보여줄 사진 개수
childAspectRatio:
1 / 1, //사진 의 가로 세로의 비율
mainAxisSpacing: 10, //수평 Padding
crossAxisSpacing: 10, //수직 Padding
),
itemBuilder: (BuildContext context, int index) {
// 사진 오른 쪽 위 삭제 버튼을 표시하기 위해 Stack을 사용함
return Stack(
alignment: Alignment.topRight,
children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
image:
DecorationImage(
fit: BoxFit.cover, //사진을 크기를 상자 크기에 맞게 조절
image: FileImage(File(images[index]!.path // images 리스트 변수 안에 있는 사진들을 순서대로 표시함
))
)
),
),
Container(
decoration: BoxDecoration(
color: Colors.black,
borderRadius:
BorderRadius.circular(5),
),
//삭제 버튼
child: IconButton(
padding: EdgeInsets.zero,
constraints: BoxConstraints(),
icon: Icon(Icons.close,
color: Colors.white,
size: 15),
onPressed: () {
//버튼을 누르면 해당 이미지가 삭제됨
setState(() {
images.remove(images[index]);
});
},
)
)
],
);
},
),
),
],
)
)
);
}
}
'Flutter' 카테고리의 다른 글
[Flutter] 웹 Mixed Content 에러 쉽고 간단하게 해결하는 방법 (0) | 2023.05.05 |
---|---|
Flutter(플러터) Firebase(파이어베이스)에서 데이터 가져와서 화면으로 보여주기 (0) | 2023.04.20 |
[Flutter] 심플한 팝업 메뉴 만들기 (0) | 2023.04.04 |
Flutter GridView(그리드뷰) 사용 방법 (0) | 2023.03.26 |
Flutter showDatePicker로 날짜 선택하기 (0) | 2023.03.25 |