패키지, 저장소 및 앱 카테고리 검색

GitHub 저장소shubham16g/multi_image_picker_view

multi_image_picker_view

image_picker 기반 위젯으로 GridView에서 여러 이미지를 선택하고 재정렬할 수 있도록 도와줍니다.

multi_image_picker_view 프로젝트 이미지
스타
28
포크
28
최근 푸시(UTC)
2025. 3. 8.
프로젝트 상태
활성

원본 README

아래는 영문 원문 스냅샷입니다. 최신 내용은 GitHub에서 확인하세요.

Multi Image Picker View Flutter

A complete widget which can easily pick multiple images from device and display them in UI. Also picked image can be re-ordered and removed easily.

🚀 LIVE DEMO OF EXAMPLE PROJECT: https://shubham16g.github.io/multi_image_picker_view/

preview

Features

  • Pick multiple images
  • Displayed in GridView
  • Reorder picked images just by dragging
  • Remove picked image
  • Limit max images
  • Fully customizable UI

Getting started

flutter pub add multi_image_picker_view

For image/file picker

flutter pub add image_picker

OR

flutter pub add file_picker

OR you can use any plugin to pick images/files.

pubspec.yaml
  multi_image_picker_view: # latest version

  image_picker: ^1.0.4
#  or
  file_picker: ^6.1.1

Usage

Define the controller
final controller = MultiImagePickerController(
    picker: (int pickCount, Object? params) async {
      // use image_picker or file_picker to pick images `pickImages`
      // use pickCount to pass as limit to the picker. Don't need to limit as it is handled internally.
      // params are the extras that can be pass if you are calling `controller.pickImages(params: yourParams)` manually.
      final pickedImages = await pickImages(pickCount);
      // convert the picked image list to `ImageFile` list and return it.
      return pickedImages.map((e) => convertToImageFile(e)).toList();
    }
);

OR

final controller = MultiImagePickerController(
    maxImages: 15,
    images: <ImageFile>[], // array of pre/default selected images
    picker: (int pickCount, Object? params) async {
      return await pickConvertedImages(allowMultiple);
    },
);
UI Implementation
MultiImagePickerView(
  controller: controller,
  padding: const EdgeInsets.all(10),
);

OR

MultiImagePickerView(
  controller: controller,
  bulder: (BuldContext context, ImageFile imageFile) {
    // here returning DefaultDraggableItemWidget. You can also return your custom widget as well.
    return DefaultDraggableItemWidget(
      imageFile: imageFile,
      boxDecoration:
        BoxDecoration(borderRadius: BorderRadius.circular(20)),
      closeButtonAlignment: Alignment.topLeft,
      fit: BoxFit.cover,
      closeButtonIcon:
        const Icon(Icons.delete_rounded, color: Colors.red),
      closeButtonBoxDecoration: null,
      showCloseButton: true,
      closeButtonMargin: const EdgeInsets.all(3),
      closeButtonPadding: const EdgeInsets.all(3),
    );
  },
  initialWidget: DefaultInitialWidget(
    centerWidget: Icon(Icons.image_search_outlined),
    backgroundColor: Theme.of(context).colorScheme.secondary.withOpacity(0.05),
    margin: EdgeInsets.zero,
  ), // Use any Widget or DefaultInitialWidget. Use null to hide initial widget
  addMoreButton: DefaultAddMoreWidget(
    icon: Icon(Icons.image_search_outlined),
    backgroundColor: Theme.of(context).colorScheme.primaryColor.withOpacity(0.2),
  ), // Use any Widget or DefaultAddMoreWidget. Use null to hide add more button.
  gridDelegate: /* Your SliverGridDelegate */,
  draggable: /* true or false, images can be reordered by dragging by user or not, default true */,
  shrinkWrap: /* true or false, to control GridView's shrinkWrap */
  longPressDelayMilliseconds: /* time to press and hold to start dragging item */
  onDragBoxDecoration: /* BoxDecoration when item is dragging */,
  padding: /* GridView padding */
  
);
ImageFile

This package use ImageFile entity to represent one image or file. Inside picker method in MultiImagePickerController, pick your images/files and convert it to list of ImageFile object and then return it. The ImageFile consists of:

final imageFile = ImageFile(
  UniqueKey().toString(), // A unique key required to track it in grid view.
  name: fileName,
  extension: fileExtension,
  path: fileFullPath,
);

Note: The package have two Extension functions to convert XFile (image_picker plugin) and PlatformFile (image_picker plugin) to ImageFile object. final imageFile = convertXFileToImageFile(xFileObject); and final imageFile = convertPlatformFileToImageFile(platformFileObject);. This functions will help you to write your picker logic easily.

ImageFileView

The ImageFileView is a widget which is used to display Image using ImageFile object. This will work on web as well as mobile platforms.

child: ImageFileView(imageFile: imageFile),
child: ImageFileView(
  imageFile: imageFile,
  borderRadius: BorderRadius.circular(8),
  fit: BoxFit.cover,
  backgroundColor: Theme.of(context).colorScheme.background,
  errorBuilder: (BuildContext context, Object error, StackTrace? trace) {
    return MyCustomErrorWidget(imageFile: imageFile)
  } // if errorBuilder is null, default error widget is used.
),
Custom UI

GridView Draggable item

  • In builder, you can use either DefaultDraggableItemWidget or your full custom Widget. i.e.
builder: (context, imageFile) {
  return Stack(
    children: [
      Positioned.fill(child: ImageFileView(imageFile: imageFile)),
      Positioned(
        top: 4,
        right: 4,
        child: DraggableItemInkWell(
          borderRadius: BorderRadius.circular(2),
          onPressed: () => controller.removeImage(imageFile),
          child: Container(
            padding: const EdgeInsets.all(5),
            decoration: BoxDecoration(
              color: Theme.of(context).colorScheme.secondary.withOpacity(0.4),
              shape: BoxShape.circle,
            ),
            child: Icon(
              Icons.delete_forever_rounded,
              size: 18,
              color: Theme.of(context).colorScheme.background,
            ),
          ),
        ),
      ),
    ],
  );
},
  • The DraggableItemInkWell can be used instead of InkWell inside builder to handle proper clicks when using laptop touchpads.
  • ImageFileView is a custom widget to show the image using ImageFile.

Initial Widget

  • You can use either DefaultInitialWidget or Custom widget or null if you don't want to show initial widget.
initialWidget: DefaultInitialWidget(
  centerWidget: Icon(Icons.image_search_outlined),
  backgroundColor: Theme.of(context).colorScheme.secondary.withOpacity(0.05),
  margin: EdgeInsets.zero,
),

OR

initialWidget: SizedBox(
  height: 170,
  width: double.infinity,
  child: Center(
    child: ElevatedButton(
      child: const Text('Add Images'),
      onPressed: () {
        controller.pickImages();
      },
    ),
  ),
),

OR

initialWidget: null,

Initial Widget

  • You can use either DefaultInitialWidget or Custom widget or null if you don't want to show initial widget.
addMoreButton: DefaultAddMoreWidget(
  icon: Icon(Icons.image_search_outlined),
  backgroundColor: Theme.of(context).colorScheme.primary.withOpacity(0.2),
),

OR

addMoreButton: SizedBox(
  height: 170,
  width: double.infinity,
  child: Center(
    child: TextButton(
      style: TextButton.styleFrom(
        backgroundColor: Colors.blue.withOpacity(0.2),
        shape: const CircleBorder(),
      ),
      onPressed: controller.pickImages,
      child: const Padding(
        padding: EdgeInsets.all(10),
        child: Icon(
          Icons.add,
          color: Colors.blue,
          size: 30,
        ),
      ),
    ),
  ),
),

OR

addMoreButton: null,
Get Picked Images

Picked Images can be get from controller.

final images = controller.images; // return Iterable<ImageFile>
for (final image in images) {
  if (image.hasPath)
    request.addFile(File(image.path!));
  else 
    request.addFile(File.fromRawPath(image.bytes!));
}
request.send();

Also controller can perform more actions.

controller.pickImages();
controller.hasNoImages; // return bool
controller.maxImages; // return maxImages
controller.removeImage(imageFile); // remove image from the images
controller.clearImages(); // remove all images (clear selection)
controller.reOrderImage(oldIndex, newIndex); // reorder the image

Custom Examples

Check the example to access all the custom examples.

custom

Migrating <1.0.0 to >=1.0.0

Changes in MultiImagePickerController
  • Inbuilt image picker is removed. You have to provide your own image/file picker logic. This will provide you more controls over image/file picking. You have to pass your picker in MultiImagePickerController.
  • allowedImageTypes removed.
  • withData removed.
  • withReadStream removed.
Changes in MultiImagePickerView
  • addMoreBuilder is removed. Now use addMoreButton to define your custom Add More Button.
  • showAddMoreButton is removed. To hide the default Add More Button, pass null in addMoreButton field.
  • initialContainerBuilder is removed. Now use initialWidget to define your custom Initial Widget.
  • showInitialContainer is removed. To hide the default Initial Widget, pass null in initialWidget field.
  • itemBuilder is removed. Now use builder to define your custom Draggable item widget. You can now define different widget for different image (ImaegFile).
  • addMoreButtonTitle is removed. Use addMoreButton and pass DefaultAddMoreWidget with custom parameters.
  • addButtonTitle is removed. Use initialWidget and pass DefaultInitialWidget with custom parameters.
  • longPressDelayMilliseconds is added. This is used to define the press and hold duration to start dragging.
  • onChange is removed.
  • MultiImagePickerView.of(context) can be used inside anywhere in MultiImagePickerView get the instance of it's components. i.e. MultiImagePickerView.of(context).controller.pickImages().

My other flutter packages

  • view_model_x - An Android similar state management package (StateFlow and SharedFlow with ViewModel) which helps to implement MVVM pattern easily.

Support

shubhamgupta16

Contributors

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Shubham Gupta GitHub avatar
GitHub 작성자

Shubham Gupta ↗

Full Stack Developer | Kotak Securities | Open Source Contributor | Flutter, Android, Kotlin, Java, React.js, PHP, SQL, Python

Kotak SecuritiesMumbai, India
언어DartHTMLRubySwiftKotlinObjective-C

분류

사용 중인 의존성

의존성 목록 4 개

프로젝트에 맞는 저장소를 선택하려면?

사용 목적에 따라 검색하고 개발 활동을 비교한 뒤 원본 저장소에서 요구 사항을 확인하세요.

  1. 이름, 작성자 또는 설명으로 검색하고 기술 주제로 범위를 좁힙니다.
  2. 스타, 포크, 최근 푸시를 함께 비교하세요. 스타는 관심의 지표이며 품질을 보장하지 않습니다.
  3. 사용하기 전에 GitHub에서 README, 라이선스, Issues를 확인하세요.

출처 및 관리

“A repository is the most basic element of GitHub.”

GitHub Docs — About repositories ↗