Build An Image Picker Wrapper Widget In Flutter

In this post, we will learn to build an image picker wrapper widget in Flutter app that can be used to switch between camera and gallery.

Introduction

For uploading images from Flutter app, Google team has a plugin called “image_picker“. With the help of this library, we can pick images from device gallery as well as take new picture from camera.

In this article we will create a wrapper button that allows us to choose between gallery and camera. Based upon the selection we will pick images to load in the Flutter application.

Setup Image Picker Icon

As usual, let’s start with a simple setup of a Material App.

import 'package:flutter/material.dart';

class AppImagePicker extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return IconButton(
      icon: Icon(Icons.camera_alt),
      iconSize: 50.0,
      onPressed: () {},
    );
  }
}

Material App Container

class MyImageApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
              decoration: BoxDecoration(
                  color: Colors.white,
                  border: Border.all(color: Colors.grey),
                  borderRadius: BorderRadius.circular(6.0),
                  boxShadow: [BoxShadow(color: Colors.blueAccent)]),
              padding: EdgeInsets.all(24.0),
              child: AppImagePicker()
            )
          ],
        ),
      )),
    );
  }
}
Setup Image Picker
Setup Image Picker

All we have so far is a camera icon button. Now on the pressed event of this button, we want to allow the user to choose between camera or gallery option.

Setup OnPressed Event For The Camera Icon

For this, we will make use of the showDialog function. It will display a Material dialog above the current contents of the app.

On the onPressed event for the icon, add:

showDialog(
            context: context,
            builder: (BuildContext context) {
              return SimpleDialog(
                  title: Text("Camera/Gallery"),
                  children: <Widget>[
                    SimpleDialogOption(
                      onPressed: () {},
                      child: const Text('Pick From Gallery'),
                    ),
                    SimpleDialogOption(
                      onPressed: () {},
                      child: const Text('Take A New Picture'),
                    ),
                  ]);
            });
Image Picker Click 1
Image Picker Click 1

Making Use Of The Image Picker

Finally we will make use of the pickImage function of the “image_picker” plugin.

/// Returns a [File] object pointing to the image that was picked.
  ///
  /// The [source] argument controls where the image comes from. This can
  /// be either [ImageSource.camera] or [ImageSource.gallery].
  ///
  /// If specified, the image will be at most [maxWidth] wide and
  /// [maxHeight] tall. Otherwise the image will be returned at it's
  /// original width and height.
  static Future<File> pickImage({
    @required ImageSource source,
    double maxWidth,
    double maxHeight,
  })

The required parameter “source” is an enum value representing camera and gallery. The other two parameters are optional values for max height and width of the image. It returns the selected image as a File object.

Wrapping Up

Let’s make some final enhancements to our image picker class. We will add some fields that can be passed via the constructor of the class:

final double maxImageWidth;
final double maxImageHeight;
final Function(File) onImageSelected;

const AppImagePicker(
  {Key key,
  this.maxImageWidth,
  this.maxImageHeight,
  @required this.onImageSelected})
  : super(key: key);

The onImageSelected callback allows us to make our image picker wrapper widget reusable.

Become A Flutter Expert With This Course

Next, add a function that handles user selection between camera and gallery.

_getImage(ImageSource src) async {
    var img = await ImagePicker.pickImage(
        source: src, maxHeight: maxImageHeight, maxWidth: maxImageWidth);
    if(onImageSelected != null) {
      onImageSelected(img);
    }
  }

Finally call the _getImage function.

Our final code:

import 'dart:io';

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

class AppImagePicker extends StatelessWidget {
  final double maxImageWidth;
  final double maxImageHeight;
  final Function(File) onImageSelected;

  const AppImagePicker(
      {Key key,
      this.maxImageWidth,
      this.maxImageHeight,
      @required this.onImageSelected})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return IconButton(
      icon: Icon(Icons.camera_alt),
      iconSize: 50.0,
      onPressed: () {
        showDialog(
            context: context,
            builder: (BuildContext context) {
              return SimpleDialog(
                  title: Text("Camera/Gallery"),
                  children: <Widget>[
                    SimpleDialogOption(
                      onPressed: () async {
                        Navigator.pop(context);//close the dialog box
                        _getImage(ImageSource.gallery);
                      },
                      child: const Text('Pick From Gallery'),
                    ),
                    SimpleDialogOption(
                      onPressed: () async {
                        Navigator.pop(context);//close the dialog box
                        _getImage(ImageSource.camera);
                      },
                      child: const Text('Take A New Picture'),
                    ),
                  ]);
            });
      },
    );
  }

  _getImage(ImageSource src) async {
    var img = await ImagePicker.pickImage(
        source: src, maxHeight: maxImageHeight, maxWidth: maxImageWidth);
    if(onImageSelected != null) {
      onImageSelected(img);
    }
  }
}