[Flutter] 폰에 저장된 이미지 가져오기

2023. 9. 22. 22:40·Web & Android/Flutter
목차
  1. image_picker 설치와 셋팅
  2. image_picker 사용법
  3. 선택한 이미지 다루기
  4. 선택한 이미지를 위젯으로 보여주기
  5. 전체 코드
  6. 숙제

image_picker 설치와 셋팅

  • pubspec.yaml 파일에 코드 추가 후 pub get
dependencies:
image_picker: ^0.8.4+4
  • ios/Runner/info.plist 파일에 코드 추가
    • 하단에 추가
    • 사용자에게 허락 팝업 띄울 때 보이는 글자들
<key>NSPhotoLibraryUsageDescription</key>
<string>사진첩좀 써도 됩니까</string>
<key>NSCameraUsageDescription</key>
<string>카메라좀 써도 됩니까</string>
<key>NSMicrophoneUsageDescription</key>
<string>마이크 권한좀 제발</string>
  • dart 파일 맨 위에 import 추가
import 'package:image_picker/image_picker.dart';
import 'dart:io';

 

image_picker 사용법

onPressed: () async {
var picker = ImagePicker();
var image = await picker.pickImage(source: ImageSource.gallery);
}

⇒ 이미지 선택 화면 뜨는 코드

  • picker.pickImage(source: ImageSource.camera);
    • 사진 선택하는 갤러리 말고 카메라를 띄워줌
  • picker.pickVideo(source: ImageSource.gallery);
    • 비디오 선택 화면이 뜸
  • picker.pickMultiImage(source: ImageSource.gallery);
    • 여러 이미지 선택이 가능

→ 고른 이미지 사이즈, 화질 조정도 가능

→ photofilters 패키지 설치하면 이미지에 필터 씌울 수 있음

 

선택한 이미지 다루기

  • 이미지는 용량이 크므로 변수에 저장하기보단 이미지의 경로만 가져와서 변수에 저장하고 사용하는게 일반적임
onPressed: () async {
var picker = ImagePicker();
var image = await picker.pickImage(source: ImageSource.gallery);
if (image != null) { // 선택 안하면 null이므로 체크
setState((){
userImage = File(image.path);
});
}
}

 

선택한 이미지를 위젯으로 보여주기

  • Image.file(userImage) 사용하면 됨
    - 이미지 파일 경로를 넣으면 이미지로 보여주는 위젯
    - userImage 변수는 MyApp() 위젯 안에 있으므로 Upload로 변수를 보내서 사용

전체 코드

import 'package:flutter/material.dart';
import './style.dart' as style;
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter/rendering.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:io';
void main() {
runApp(
MaterialApp(
theme: style.theme,
home: MyApp()
));
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
var tab = 0; // 1. 현재 상태 저장
var list = [1, 2, 3];
var map = {'name':'john', 'age':20};
var data = [];
var userImage;
addData(a) {
setState(() {
data.add(a);
});
}
getData() async {
var result = await http.get(Uri.parse('https://codingapple1.github.io/app/data.json'));
var result2 = jsonDecode(result.body);
setState(() {
data = result2;
});
}
@override
void initState() {
super.initState();
getData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Instagram'),
actions: [
IconButton(
icon: Icon(Icons.add_box_outlined),
onPressed: () async {
var picker = ImagePicker();
var image = await picker.pickImage(source: ImageSource.gallery);
if(image != null) {
setState(() {
userImage = File(image.path);
});
}
Navigator.push(context,
MaterialPageRoute(builder: (c) => Upload( userImage : userImage) )
);
},
iconSize: 30,
)
]),
body: [Home(data : data, addData : addData), Text('샵페이지')][tab], // 2. state에 따라 tab 보이는 상태 변경
bottomNavigationBar: BottomNavigationBar(
showSelectedLabels: false,
showUnselectedLabels: false,
onTap: (i){
setState(() {
tab = i;
});
},
items: [
BottomNavigationBarItem(icon: Icon(Icons.home_outlined), label: '홈'),
BottomNavigationBarItem(icon: Icon(Icons.shopping_bag_outlined), label: '샵')
],
),
);
}
}
class Home extends StatefulWidget {
const Home({Key? key, this.data, this.addData}) : super(key: key);
final data, addData;
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
var scroll = ScrollController();
getMore() async {
var result = await http.get(Uri.parse('https://codingapple1.github.io/app/more1.json'));
var result2 = jsonDecode(result.body);
widget.addData(result2);
}
@override
void initState() {
super.initState();
scroll.addListener(() { // 스크롤바 높이 측정 코드
if(scroll.position.pixels == scroll.position.maxScrollExtent) {
getMore();
}
});
}
@override
Widget build(BuildContext context) {
if (widget.data.isNotEmpty) {
return ListView.builder(
itemCount: widget.data.length,
controller: scroll,
itemBuilder: (c, i) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.network(widget.data[i]['image']),
Container(
constraints: BoxConstraints(maxWidth: 600),
padding: EdgeInsets.all(20),
width: double.infinity,
child: Column(
children: [
Text('좋아요 ${widget.data[i]['likes'].toString()}'),
Text(widget.data[i]['date']),
Text(widget.data[i]['content'])
],
),
)
],
);
}
);
} else {
return Text('로딩중임');
}
}
}
class Upload extends StatelessWidget {
const Upload({Key? key, this.userImage}) : super(key: key);
final userImage;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Image.file(userImage),
Text('이미지업로드화면'),
TextField(),
IconButton(
onPressed: (){
Navigator.pop(context);
},
icon: Icon(Icons.close)
),
],
)
);
}
}

숙제

→ 발행 버튼 누르면 유저가 입력한 글과 사진 게시물로 보여주기

  1. 우선 발행 버튼 하나 만들고
  2. Scaffold( resizeToAvoidBottomInset: false, appBar: AppBar( actions: [ IconButton(onPressed: (){}, icon: Icon(Icons.send)) ]), (생략)
  3. 유저가 입력한 글과 사진을 MyApp 안에 state에 저장해둠
    • 유저가 글 입력하면 userContent에 저장되게 만들기
      (Upload페이지)
      TextField(onChanged: (text){ setUserContent(text); })
  4. class _MyAppState extends State<MyApp> { var tab = 0; var data = []; var userImage; var userContent; setUserContent(a){ setState(() { userContent = a; }); } (생략)
  5. 발행 버튼 누르면 var data = [] 에 게시물 데이터 하나 추가
    • 게시물 데이터엔 유저가 선택한 사진과 글이 들어가면 됨
    • list 맨 앞부분에 자료 추가하고 싶으면 data.insert(0, 자료) 사용
    class _MyAppState extends State<MyApp> {
    var tab = 0;
    var data = [];
    var userImage;
    var userContent;
    addMyData(){
    var myData = {
    'id': data.length,
    'image': userImage,
    'likes': 5,
    'date': 'July 25',
    'content': userContent,
    'liked': false,
    'user': 'John Kim'
    };
    setState(() {
    data.insert(0, myData);
    });
    }
    (생략)
    • Upload 페이지의 발행 버튼 누르면 저 함수 실행
      Scaffold(
      resizeToAvoidBottomInset: false,
      appBar: AppBar( actions: [
      IconButton(onPressed: (){ addMyData(); }, icon: Icon(Icons.send))
      ]),
      (생략)
  6. 이상한 건 if문으로 예외 처리
    - 3번까지 하고 돌리면 콘솔창에 에러남
    - type '_File' is not a subtype of type 'String’
    - 이미지 보여줄 때 Image.network() 여기에 ‘https://어쩌구’ 이런 거 넣어서 보여주고 있는데 사용자가 선택한 건 File 타입이기 때문에 타입 에러 발생
    - 그래서 삼중 연산자를 통해 이미지 경로가 문자이면 무엇을, 그에 아니라면 이것을 보여달라고 코드 구현
  7. Image.network(widget.data[i]['image']) // -> 이렇게 변경 widget.data[i]['image'].runtimeType == String ? Image.network(widget.data[i]['image']) : Image.file(widget.data[i]['image']),
저작자표시 비영리 변경금지 (새창열림)

'Web & Android > Flutter' 카테고리의 다른 글

[Flutter] 위젯 클릭 - GestureDetector  (0) 2023.09.22
[Flutter] DB 없이 데이터 저장하기 - Shared preferences  (0) 2023.09.22
[Flutter] 페이지 나누기 - 라우터 사용 (/)  (0) 2023.09.22
[Flutter] 페이지 나누기 - Navigator  (0) 2023.09.22
[Flutter] 페이지 나누기 - Tab  (0) 2023.09.22
  1. image_picker 설치와 셋팅
  2. image_picker 사용법
  3. 선택한 이미지 다루기
  4. 선택한 이미지를 위젯으로 보여주기
  5. 전체 코드
  6. 숙제
'Web & Android/Flutter' 카테고리의 다른 글
  • [Flutter] 위젯 클릭 - GestureDetector
  • [Flutter] DB 없이 데이터 저장하기 - Shared preferences
  • [Flutter] 페이지 나누기 - 라우터 사용 (/)
  • [Flutter] 페이지 나누기 - Navigator
woojin._.
woojin._.
여러가지 개발을 해보며 발생하는 이야기들에 대한 블로그입니다:)
  • woojin._.
    Jin's Dev Story
    woojin._.
  • 전체
    오늘
    어제
    • 분류 전체보기 (794)
      • Tools (25)
        • eGovFrame (3)
        • GeoServer (3)
        • QGIS (2)
        • LabelImg (2)
        • Git (6)
        • GitHub (1)
        • Eclipse (7)
        • Visual Studio (1)
      • Web & Android (121)
        • SpringBoot (37)
        • Three.js (2)
        • Spring Data JPA (9)
        • 스프링 부트 쇼핑몰 프로젝트 with JPA (25)
        • Thymeleaf (4)
        • Spring Security (15)
        • Flutter (29)
      • Programming Language (61)
        • JAVA (27)
        • JavaScript (14)
        • Dart (2)
        • Python (15)
        • PHP (3)
      • Database (43)
        • PostgreSQL (32)
        • MYSQL (7)
        • Oracle (3)
        • MSSQL (1)
      • SERVER (17)
        • TCP_IP (3)
        • 리눅스 (7)
        • AWS (7)
      • Coding Test (410)
        • 백준[JAVA] (76)
        • 프로그래머스[JAVA] (257)
        • 알고리즘 고득점 Kit[JAVA] (3)
        • SQL 고득점 Kit[ORACLE] (74)
      • CS 지식 (49)
        • [자료구조] (14)
        • [네트워크] (12)
        • [데이터베이스] (10)
        • [알고리즘] (9)
        • [운영체제] (4)
      • 기타 (6)
      • 자격증 & 공부 (62)
        • 정보처리기사 (2)
        • SQLD (6)
        • 네트워크관리사 2급 (5)
        • 리눅스마스터 1급 (44)
        • 리눅스마스터 2급 (1)
        • ISTQB (3)
        • 시스템보안 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 인기 글

  • 태그

    스프링
    springboot
    postgresql
    시큐리티
    JPA
    spring
    CS지식
    pcce 기출문제
    programmers
    python
    Linux
    리눅스
    프로그래머스
    Flutter
    리눅스마스터
    데이터베이스
    플러터
    DB
    baekjoon
    스프링부트
    스프링 부트 쇼핑몰 프로젝트 with JPA
    Java
    리눅스마스터 1급
    backjoon
    자바
    백준
    CS
    Oracle
    Spring Security
    데이터
  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
woojin._.
[Flutter] 폰에 저장된 이미지 가져오기

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.