플러터 (flutter)

갤러리에서 이미지를 선택하는 flutter ImagePicker

CreatoMaestro 2023. 6. 30. 20:38
반응형

이번에는 갤러리에서 이미지를 선택하는 ImagePicker에 대해 알아본다.

기능은 다음과 같다.

  1) 홈 화면에서 floating action button을 클릭하면 선택할 수 있는 갤러리로 넘어간다.

  2) 갤러리에서 사진을 선택하면 이미지를 띄우는 화면으로 넘어간다.

 

다음은 완성한 앱의 화면이다.

앱 화면 결과
완성된 앱 화면

시작화면은 아직 이미지를 선택하지 않은 상태이다.

여기서 아래 버튼을 클릭하면 갤러리 화면으로 넘어간다.

갤러리 화면에서 사진을 클릭하면 화면에 사진이 뜬다.

이 상태에서 버튼을 다시 누르면 다른 이미지를 선택할 수 있다.

 

이제 앱을 만들어보도록 하자

우선 pubspec.yaml로 들어가서 dependencies 안에 image_picker를 추가해 준다.

이후에 android/app/src/main 폴더에 있는 AndroidManifest.xml로 바꾼다.

여기서 manifest 안에 uses-permission을 추가해 준다.

이 퍼미션은 앱이 갤러리에 접근할 수 있도록 해준다.

그다음 android/app/src 폴더에 있는 build.gradle 파일을 열어준다.

defaultConfig 안에 있는 minSdkVersion을 21로 해준다.

이렇게 하는 이유는 image picker를 사용하기 위한 최소 SDK가 21이기 때문이다.

 

이제 코드를 써보자

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

void main() {
  runApp(ImageWallPaper());
}

'dart:io'는 async와 await을 사용하기 위해 import 해준다.

또한 image_picker를 사용하기 위한 dart 파일을 import 해준다.

 

이후 ImageWallPaper()를 실행하도록 해준다.

이 클래스는 우리가 만들 앱의 메인 페이지이다.

class ImageWallPaper extends StatefulWidget {

  //Creater
  ImageWallPaper({Key? key}) : super(key: key);

  @override
  State<ImageWallPaper> createState() => _ImageWallPaperState();
}

ImageWallPaper를 StatefulWidget으로 생성해 준다.

생성자를 생성해 주고, override를 통해 State를 만들어준다.

_ImageWallPaperState는 ImageWallPaper 클래스의 State 클래스이다.

 

class _ImageWallPaperState extends State<ImageWallPaper> {

  XFile? image;

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.initState();
  }

  void floatingPressed() async {
    image = await ImagePicker().pickImage(source: ImageSource.gallery);
    setState(() {

    });
  }

ImageWallPaper 클래스의 상태 클래스인 _ImageWallPaperState를 생성해 준다.

 

XFile? image에 갤러리에서 받아온 파일을 받아온다.

XFile은 image picker에서 받아온 파일의 형태이다.

 

initState()와 dispose()를 override 해준다.

이 글에서는 사용하지 않지만 다음 글에서 사용하기 위해 넣어준다.

 

floatingPressed는 floating action button을 눌렀을 때 실행할 함수이다.

ImagePicker에서 이미지를 받아올 때까지 기다려야 하기 때문에 async와 await을 사용해 코드가 완료될 때 까지 기다릴 수 있도록 했다.

 

image = await ImagePicker().pickImage(source: ImageSource.gallery);

ImagePicker()는 우리가 배우는 ImagePicker의 생성자를 나타낸다.

pickImage는 우리가 이미지를 받아올 것임을 의미한다.

source 파라미터에 ImageSource.gallery라는 값을 넣어주었는데 이는 갤러리에서 이미지를 가져올 것임을 알려준다.

 

  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark(),
      home: Scaffold(
        floatingActionButton: FloatingActionButton(
          onPressed: floatingPressed,
          child: Icon(Icons.change_circle),
        ),
        body: image != null? imageWidget(image) : initScreen(),
      ),
    );
  }
}

위 코드는 widget을 반환해 주는 코드이다.

theme: ThemeData.dark()는 앱의 테마를 어두운 테마로 바꿔준다.

Scaffold 안에 floatingActionButtion 파라미터와 body 파라미터를 넣어주었다.

Scaffold 위젯 트리

floatingActionButton에는 FloatingActionButton을 넣어준다.

이 버튼은 항상 화면의 오른쪽 아래에 위치한다.

이 버튼을 누르면 갤러리로 들어갈 수 있도록 한다.

그러기 위해서 방금 만들었던 floatingPressed 메서드를 넣어준다.

child로는 아이콘을 넣어준다.

 

body의 경우 상태에 따라 화면이 바뀌도록 한다.

만약 image가 null이라면 initScreen을 띄우고, null이 아니라면 imageWidget에서 반환된 위젯을 띄운다.

 

Widget imageWidget(XFile? image) {
  return Center(
    child: Image.file(File(image!.path)),
  );
}

Center 위젯을 반환에 주는 위젯이다.

Image.file을 통해 반환받은 image를 중앙 정렬하여 띄운다.

 

Widget initScreen() {
  return const Center(
    child: Text(
      "Please select image!",
      style: TextStyle(
        fontSize: 20.0,
      ),
    ),
  );
}

다음 위젯은 이미지가 선택되지 않았을 때(image == null 일 때) 화면에 나오는 위젯이다.

화면에 텍스트로 이미지를 선택하라고 한다.

맨 처음 앱을 실행하면 나오는 화면이다.

 

전체 코드는 다음과 같다.

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

void main() {
  runApp(ImageWallPaper());
}

class ImageWallPaper extends StatefulWidget {

  //Creater
  ImageWallPaper({Key? key}) : super(key: key);

  @override
  State<ImageWallPaper> createState() => _ImageWallPaperState();
}

class _ImageWallPaperState extends State<ImageWallPaper> {

  XFile? image;

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.initState();
  }

  void floatingPressed() async {
    image = await ImagePicker().pickImage(source: ImageSource.gallery);
    setState(() {

    });
  }

  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark(),
      home: Scaffold(
        floatingActionButton: FloatingActionButton(
          onPressed: floatingPressed,
          child: Icon(Icons.change_circle),
        ),
        body: image != null? imageWidget(image) : initScreen(),
      ),
    );
  }
}

Widget imageWidget(XFile? image) {
  return Center(
    child: Image.file(File(image!.path)),
  );
}

Widget initScreen() {
  return const Center(
    child: Text(
      "Please select image!",
      style: TextStyle(
        fontSize: 20.0,
      ),
    ),
  );
}

 

 

*"글에서 사용한 사진 저작물은 한국관광공사에서 2020년 작성하여 공공누리 제1유형으로 개방한 '광주 맥문동 숲길'을 이용하였으며,해당 저작물은 'https://www.kogl.or.kr/recommend/recommendDivView.doatcUrl=personal&recommendIdx=38055&division=img'

에서 무료로 다운받으실 수 있습니다."

반응형