본문 바로가기
Flutter

[Flutter] 갤러리에서 이미지 가져오기(2)

by dong_seok 2023. 8. 30.

지난 포스팅때 pickMultiImage()를 이용해서 갤러리에서 이미지를 가져와 봤습니다. 이제 이 코드를 제가 만들던 페이지에 옮겨서 작업을 이어나가려했는데 두가지 문제가 발생하였습니다.

 

1. pickMultiImage( ) 갯수 제한 설정 불가

한번에 이미지를 여러개 선택해서 List 형태로 가져다 쓸 수 있는건 좋았지만 갯수 제한을 설정할 수 없어서 너무 많은 이미지를 가져와서 오류가 발생하는 문제가 있었습니다. 저는 2개의 이미지만 가져올 수 있도록 만들고 싶었기 때문에 방법을 열심히 찾아봤지만 갯수를 지정해주는 방법은 찾지 못했습니다... if문을 사용해서 3개이상의 이미지가 선택되면 이미지가 안나오고 버튼이 남아있게끔 구현하였지만 임시방편일뿐 선택되는 이미지의 갯수 자체를 고정 시키진 못하였습니다.

 

2. RenderBox was not Laid Out

코드를 제가 만들던 페이지에 옮겨서 실행했더니 아래와 같은 오류가 발생하였습니다.

 

 

찾아보니 이 오류가 발생하는 이유는 다른 스크롤 가능한 위젯 내에 하나의 스크롤 가능한 위젯을 직접 추가했기 때문이었습니다. 해결방법으로 Gridview를 Expanded로 감싸는 방법이 있길래 시도해보았지만 실패하였습니다.

 

 

 이외에도 다른 몇가지 방법을 사용해보았지만 위의 두가지 문제점을 완벽하게 해결하지 못해서 결국 다른 방법을 찾게 되었습니다. 한번에 이미지를 여러장 가져오는 pickMultiImage()을 사용하는게 아니라 .pickImage()를 2개 사용하기로 하였습니다. 

 

import 'dart:io';

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

class ImagePickerScreen extends StatefulWidget {
  const ImagePickerScreen({Key? key}) : super(key: key);

  @override
  State<ImagePickerScreen> createState() => _ImagePickerScreenState();
}

class _ImagePickerScreenState extends State<ImagePickerScreen> {
  XFile? _pickedFile1;
  XFile? _pickedFile2;

  List<File> pickedimage = [];

  @override
  Widget build(BuildContext context) {
    final _imageSize = MediaQuery.of(context).size.width / 4;
    return Scaffold(
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 10),
          child: Column(
            children: [
              Padding(
                padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
                child: Row(
                  children: [
                    if (_pickedFile1 == null) //여기ㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣ
                      Container(
                        height: 80,
                        constraints: BoxConstraints(
                          minHeight: _imageSize,
                          minWidth: _imageSize,
                        ),
                        child: GestureDetector(
                          onTap: () {
                            _getPhotoLibraryImage1();
                          },
                          child: Center(
                            child: Icon(
                              Icons.camera_alt_outlined,
                              size: 60,
                              color: Colors.grey,
                            ),
                          ),
                        ),
                        decoration: BoxDecoration(
                          border: Border.all(width: 2, color: Colors.grey),
                        ),
                      )
                    else
                      Center(
                          child: Stack(
                        children: [
                          Container(
                            width: _imageSize,
                            height: _imageSize,
                            decoration: BoxDecoration(
                              image: DecorationImage(
                                  image: FileImage(File(_pickedFile1!.path)),
                                  fit: BoxFit.cover),
                            ),
                          ),
                          Positioned(
                            top: 5,
                            right: 5,
                            child: GestureDetector(
                              onTap: () {
                                setState(() {
                                  _pickedFile1 = null;
                                });
                              },
                              child: const Icon(
                                Icons.cancel_rounded,
                                color: Colors.black87,
                              ),
                            ),
                          )
                        ],
                      )),
                    SizedBox(
                      width: 20,
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  _getPhotoLibraryImage1() async {
    final pickedFile =
        await ImagePicker().pickImage(source: ImageSource.gallery);
    if (pickedFile != null) {
      setState(() {
        _pickedFile1 = pickedFile;
        pickedimage.add(File(pickedFile.path));
      });
    } else {
      if (kDebugMode) {
        print('이미지 선택안함');
      }
    }
  }
}

 

다음과 같이 코드를 구현하여서 이미지가 선택되지 않으면 icon이 지정된 Container 위젯이 실행되고 이미지를 선택하면 그 이미지로 채워지게끔 구현하였습니다. 코드를 실행시켜보면

 

 

자유롭게 이미지를 첨부고하고 취소하고 할 수 있습니다. 제가 가져오려는 이미지는 두개니까 동일한 방법으로 하나의 Container()를 추가해서 두개의 이미지를 가져올 수 있도록 하였습니다.

 

 

2개의 이미지만 깔끔하게 가져오는 모습을 볼 수 있습니다. 하지만 아쉬운점이 사용자 입장에서 두번째 이미지를 먼저 선택했을때 첫번째 이미지가 비어있다는 점과 첫번째 이미지를 먼저 지웠을때 두번째 이미지가 그 자리에 그대로 남아 있다는 점이 아쉬웠습니다. 그래서 조건문을 사용해서 코드를 다음과 같이 수정해 주었습니다.

 

_getPhotoLibraryImage2() async {
    final pickedFile =
    await ImagePicker().pickImage(source: ImageSource.gallery);
    if (pickedFile != null) {
      setState(() {
        if (_pickedFile1 == null)
          _pickedFile1 = pickedFile;
        else
          _pickedFile2 = pickedFile;
        pickedimage.add(File(pickedFile.path));        
      });      
    } else {
      if (kDebugMode) {
        print('이미지 선택안함');
      }
    }
  }

 

setState(() {
              if (_pickedFile2 != null)
                [
                  _pickedFile1 = _pickedFile2,
                  _pickedFile2 = null,
                  pickedimage[0] = pickedimage[1],
                  pickedimage.removeLast(),
                ];
               else
                 [
                    _pickedFile1 = null,
                    pickedimage.removeLast(),
                 ];
             });

 

이렇게 코드를 수정하고나니까!!

 

 

항상 첫번째 이미지 먼저 채워지고 삭제되는 모습을 볼 수 있습니다! 제가 원래 작성하던 코드에 가져다 넣어도 오류가 생기지않고 정상적으로 잘 작동하는 모습을 볼 수 있었습니다!

 

참고자료

https://guitaryc.tistory.com/46

 

 

 

'Flutter' 카테고리의 다른 글

[Flutter] 오류 (Error Opening Emulator)  (0) 2023.08.31
[Flutter] 갤러리에서 이미지 가져오기(1)  (0) 2023.08.30
[Flutter] Today 날짜 가져오기  (0) 2023.08.27
[Flutter] http 통신(Post)  (0) 2023.08.26
[Flutter] Listview.builder  (0) 2023.08.22

댓글