You are currently viewing Flutter: Displaying File Images

Flutter: Displaying File Images

In Flutter, images can come from different sources. You might use built-in pictures from your app (called asset images), or you might want to show pictures that the user picks from their phone.

When someone takes a photo or chooses one from their gallery, that image becomes a file image. To show it in your app, you need to load it from the device’s storage.

In this article, you’ll learn:

  • What file images are and how they’re different from asset images
  • How to pick an image from the device
  • How to display it safely and clearly in your app

Let’s get started!

What Are File Images?

A file image is a picture that comes from the user’s device—like something saved in their photo gallery or taken with the camera. These images aren’t built into your app like asset images. Instead, they appear while the app is running.

You’ll use file images when:

  • The user selects a photo from their phone
  • The user takes a new picture with the camera
  • Your app downloads and saves an image on the device

File images make your app feel more personal because users can see their own photos.

Setting Up the Project

To show images from the device, we need some tools.

Step 1: Add Needed Packages

In your pubspec.yaml file, add these:

dependencies:
  image_picker: ^1.1.2
  permission_handler: ^12.0.0+1

Then run this command:

flutter pub get

These packages help your app pick pictures and ask for permission to use the camera or gallery.

Step 2: Handle Permissions (for Android and iOS)

Your app needs permission to use the camera or pick images from the gallery.

  • On Android:
    Open android/app/src/main/AndroidManifest.xml and add these inside the <manifest> tag:
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

  • On iOS:
    Open ios/Runner/Info.plist and add:
<key>NSCameraUsageDescription</key>
<string>This app needs access to the camera to take photos.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs access to your photo library.</string>

If your app also needs to record videos (which can include sound), then you must ask for microphone permission on iOS too.

To do that, add this to your Info.plist file:

<key>NSMicrophoneUsageDescription</key>
<string>This app needs access to the microphone to record audio.</string>

This message appears in the system popup when the app asks for microphone access. Always write a clear and friendly reason so users know why it’s needed.

Without these, your app won’t be able to use the camera or pick images.

Displaying a File Image

Once you have a file—like a photo picked from the gallery—you can show it using Flutter’s FileImage class. This class tells Flutter to load the image from the device’s local storage.

Here’s a simple example:

import 'dart:io';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('File Image')),
        body: Center(
          child: Image(
            image: FileImage(
              File('/storage/emulated/0/Download/mortal-kombat.jpg'),
            ),
          ),
        ),
      ),
    );
  }
}

Just replace '/storage/emulated/0/Download/mortal-kombat.jpg' with the actual path to your file. This is often the path returned by an image picker after a user selects a photo.

FileImage is like AssetImage, but instead of loading pictures built into your app, it loads them from the user’s device.

Flutter Gallery [File Image]

Note: It’s best to test this on a real device—not a simulator—because features like the camera and gallery access may not work properly or at all in simulators. Real devices give you the full experience, including permission prompts and actual file handling.

If you get a “permission denied” error when running the app, it means the app can’t access the camera or photos yet. To fix this, long-press the app icon, tap App Info (or the little “i” button), and make sure permissions for media and camera are turned on.

Real-World Example 1: Pick and Show an Image from Gallery

Let’s build a widget where a user taps a button, picks a photo, and sees it on the screen.

import 'dart:io';

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'File Image Example',
      home: Scaffold(
        appBar: AppBar(title: const Text('Pick Image from Gallery')),
        body: const Center(child: FileImagePicker()),
      ),
    );
  }
}

class FileImagePicker extends StatefulWidget {
  const FileImagePicker({super.key});

  @override
  State<FileImagePicker> createState() => _FileImagePickerState();
}

class _FileImagePickerState extends State<FileImagePicker> {
  final ImagePicker _picker = ImagePicker();
  File? _imageFile;

  Future<void> _pickImage() async {
    try {
      final pickedFile = await _picker.pickImage(source: ImageSource.gallery);

      if (pickedFile != null) {
        setState(() {
          _imageFile = File(pickedFile.path);
        });
      }
    } catch (e) {
      // Handle any errors here (optional)
      debugPrint('Error picking image: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        ElevatedButton(onPressed: _pickImage, child: const Text('Pick Image')),
        const SizedBox(height: 20),
        _buildImagePreview(),
      ],
    );
  }

  Widget _buildImagePreview() {
    if (_imageFile != null) {
      return Image.file(
        _imageFile!,
        width: 200,
        height: 200,
        fit: BoxFit.cover,
      );
    } else {
      return const Text('No image selected');
    }
  }
}

What’s Happening?

  • The user taps the button to choose a photo from their gallery.
  • If a photo is picked, we turn it into a File.
  • The Image.file() widget then shows the photo right on the screen.
Flutter Gallery [File ImagePicker]

This is a simple and fun way to let users add their own pictures to your app.

Real-World Example 2: Take a Photo with the Camera

In addition to picking an image from the gallery, you can also let users take a new photo with their camera and instantly display it in your app.

The following example demonstrates how to implement this feature:

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Image Picker Example',
      home: Scaffold(
        appBar: AppBar(title: Text('Pick or Take Photo')),
        body: const Center(child: ImagePickerExample()),
      ),
    );
  }
}

class ImagePickerExample extends StatefulWidget {
  const ImagePickerExample({super.key});

  @override
  State<ImagePickerExample> createState() => _ImagePickerExampleState();
}

class _ImagePickerExampleState extends State<ImagePickerExample> {
  final ImagePicker _picker = ImagePicker();
  File? _imageFile;
  bool _isLoading = false;

  // Function to pick image from gallery
  Future<void> _pickImage() async {
    setState(() {
      _isLoading = true;
    });

    try {
      final pickedFile = await _picker.pickImage(source: ImageSource.gallery);

      if (pickedFile != null) {
        setState(() {
          _imageFile = File(pickedFile.path);
        });
      } else {
        _showError('No image selected');
      }
    } catch (e) {
      _showError('Error picking image: $e');
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  // Function to take a photo with the camera
  Future<void> _takePhoto() async {
    setState(() {
      _isLoading = true;
    });

    try {
      final pickedFile = await _picker.pickImage(source: ImageSource.camera);

      if (pickedFile != null) {
        setState(() {
          _imageFile = File(pickedFile.path);
        });
      } else {
        _showError('No photo taken');
      }
    } catch (e) {
      _showError('Error taking photo: $e');
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  // Show error message as a dialog
  void _showError(String message) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Error'),
        content: Text(message),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('OK'),
          ),
        ],
      ),
    );
  }

  // Method to display the image or a placeholder if no image is selected
  Widget _buildImagePreview() {
    if (_imageFile != null) {
      return Image.file(
        _imageFile!,
        width: 200,
        height: 200,
        fit: BoxFit.cover,
      );
    } else {
      return const Text('No image selected');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        if (_isLoading)
          const CircularProgressIndicator()
        else ...[
          ElevatedButton(
            onPressed: _pickImage,
            child: const Text('Pick Image from Gallery'),
          ),
          const SizedBox(height: 20),
          ElevatedButton(
            onPressed: _takePhoto,
            child: const Text('Take a Photo with Camera'),
          ),
        ],
        const SizedBox(height: 20),
        _buildImagePreview(), // Display the selected or taken image here
      ],
    );
  }
}

What’s Happening?

  • Pick Image from Gallery: Users can choose an image from their gallery, and it is displayed right away.
  • Take a Photo with Camera: Users can take a new photo, which is immediately shown on the screen.
Flutter Gallery [File ImagePicker and Camera]

Key Features:

  • Loading Indicator: A spinner appears while the app processes the image.
  • Error Handling: If an error occurs (e.g., no image is selected), an error message is shown.
  • Image Preview: The selected or taken image is displayed immediately.

This approach allows users to either pick an image or take a new photo, making it ideal for apps that need to handle user-uploaded pictures.

Handling Errors and Permissions

Sometimes things can go wrong—like the user canceling the action or denying permissions. Here’s how to keep your app stable and user-friendly:

  • Always check if the selected file is null before using it.
  • Provide a fallback message or widget if no image is chosen.
  • Be clear and polite when requesting permissions.

For example, you can handle errors like this:

if (_imageFile == null) {
  return Text('No image selected');
} else {
  return Image.file(_imageFile!);
}

By doing this, your app avoids crashes and offers a smooth user experience.

Tips and Best Practices

  • Always check if the image file exists before trying to display it.
  • Test on a real device, as some features may not work well in emulators.
  • Ensure you handle permissions for both Android and iOS.
  • Resize large images if necessary to keep your app fast and light.

Conclusion

In this article, you learned how to display images from a user’s device in Flutter. File images are ideal for apps that involve photo sharing, camera usage, or where the user adds their own images.

To summarize, we:

  • Explored the difference between asset and file images.
  • Learned how to pick images from the gallery.
  • Implemented functionality to take photos with the camera.
  • Displayed file images using Image.file().
  • Handled errors and permissions effectively.

Now you’re ready to incorporate photo-based features into your Flutter apps!