Flutter Learning Roadmap

12 min

12 min

Ashutosh Rawat

Published on Apr 22, 2024

Assets and Images in Flutter: What Files Can Enhance Your App's Visual Appeal and Functionality?

Introduction

Welcome to our blog on "Assets and Images in Flutter: What Files Can Enhance Your App's Visual Appeal and Functionality?" Flutter has revolutionized the way developers create mobile applications, offering a rich set of features and capabilities. One crucial aspect of building engaging Flutter apps is leveraging assets and images effectively.

Importance of Assets and Images

Assets encompass a wide range of files, including images, icons, fonts, and configuration files, that are bundled and deployed with your app. These resources are essential for providing visual elements, customizing typography, and configuring app settings. Meanwhile, images serve as the visual backbone of your app, conveying information, enhancing aesthetics, and creating engaging user experiences.

Structure of the Blog

This blog is structured into four main sections, each focusing on a key aspect of assets and images in Flutter:

  1. Adding Assets and Images

  2. Displaying Images from the Internet

  3. Implementing Fade-In Image with Placeholder

  4. Playing and Pausing Videos

Within each section, we'll provide detailed explanations, step-by-step guides, and practical examples to help you master the concepts and techniques discussed.

Ready to level up your Flutter skills? Dive into our Flutter Learning series, where you'll find comprehensive guides and tutorials to master various aspects of Flutter app development. This blog is part of the Flutter Learning Roadmap, designed to help you navigate your learning journey seamlessly.

Before you continue, make sure to check out the previous blog in the series, where we explored scrolling techniques in Flutter. Happy learning!

Adding Assets and Images

Flutter apps bundle and deploy assets such as JSON files, configuration files, icons, and various image formats, enhancing user experiences with diverse content accessible at runtime.

Adding Assets and Images

In Flutter, assets and images are integral components of app development, enhancing both visual appeal and functionality. Let's delve into how to effectively add assets and images to your Flutter app.

Specifying Assets in Flutter

Flutter utilizes the pubspec.yaml file, located at the root of your project, to identify assets required by your app. Here is an example:

flutter:
  assets:
    - assets/my_icon.png
    - assets/background.pn

You can also include all assets under a directory by specifying the directory name with the / character at the end:

flutter:
  assets:
    - directory/
    - directory/subdirectory

It's important to note that only files located directly in the directory are included, with resolution-aware asset image variants being the exception. To include files located in subdirectories, create an entry per directory.

Asset Bundling Process

The assets subsection of the flutter section in pubspec.yaml specifies files that should be included with the app. During the build process, Flutter places these assets into a special archive called the asset bundle, which the app reads from at runtime.

The order in which assets are declared doesn't matter, and the actual directory name used (assets in the example) is arbitrary. Flutter handles the bundling of assets automatically, ensuring they are available for use within the app.

Loading Assets into Your Flutter App

Once assets are specified in the pubspec.yaml file and bundled with the app, your Flutter app can access them through an AssetBundle object. There are two main methods for loading assets: loadString() for loading text assets and load() for loading images or binary assets.

Loading text assets

In Flutter, the rootBundle object provides easy access to the main asset bundle for each app. While it's possible to load assets directly using the rootBundle from package:flutter/services.dart, it's recommended to obtain the AssetBundle for the current DefaultAssetBundle.

This approach allows for runtime substitution of asset bundles, beneficial for localization or testing scenarios. Typically, DefaultAssetBundle.of() is used to indirectly load assets like JSON files. Outside Widget contexts or without access to an tAssetBundle handle, rootBundle can be utilized to load assets directly.

import 'package:flutter/services.dart' show rootBundle;

Future<String> loadAsset() async {
  return await rootBundle.loadString('assets/config.json');
}
Loading images

For loading images, use the AssetImage class in a widget's build() method:

return const Image(image: AssetImage('assets/background.png'));

Flutter also supports resolution-aware image assets, allowing the app to load images appropriate for the device's pixel ratio.

Resolution-Aware Image Assets

Flutter supports resolution-aware image assets, ensuring optimal image quality across various device pixel ratios. By organizing images into directories with specific identifiers, Flutter automatically selects the appropriate asset based on the device's pixel ratio.

.../image.png
.../Mx/image.png
.../Nx/image.png
...etc

Images should be organized in a directory structure that includes variants for different pixel ratios, such as 1.5x, 2.0x, 3.0x, etc.

In Flutter, specifying the main asset or its parent directory in the pubspec.yaml assets section bundles resolution-aware image variants automatically. The main asset entry, if not a real file, defaults to the lowest resolution variant for devices. Utilizing the default asset bundle ensures resolution awareness when loading images.

Asset Images in Package Dependencies

When loading images from package dependencies, Flutter requires specifying the package argument with AssetImage. This ensures the proper resolution of assets from the package directory structure.

Suppose your application relies on a package named my_icons, with the following directory layout:

.../pubspec.yaml
.../icons/heart.png
.../icons/1.5x/heart.png
.../icons/2.0x/heart.png
...etc

To load the image, use:

  return const AssetImage('icons/heart.png', package: 'my_icons');
}

Sharing Assets with the Underlying Platform

Flutter assets are accessible to platform code using platform-specific APIs, such as AssetManager on Android and NSBundle on iOS.

Loading Flutter Assets in Android and iOS

On Android and iOS platforms, Flutter assets can be accessed through platform-specific APIs. For example, on Android, assets are available through the AssetManager API, while on iOS, they are accessible via NSBundle.

flutter:
  assets:
    - icons/heart.png

This reflects the following structure in your Flutter app.

.../pubspec.yaml
.../icons/heart.png
...etc

To access icons/heart.png from your Java plugin code:

AssetManager assetManager = registrar.context().getAssets();
String key = registrar.lookupKeyForAsset("icons/heart.png");
AssetFileDescriptor fd = assetManager.openFd(key);

Updating the App Icon and Launch Screen

Flutter apps can customize their app icons and launch screens using platform-specific mechanisms. On Android, you can update the app icon by replacing the placeholder images in the res directory, while on iOS, you can customize the launch screen by modifying the LaunchImage.imageset directory. These customizations enhance the branding and user experience of your Flutter app.

Displaying Images from the Internet

Displaying images from the internet is a common requirement in mobile apps. Flutter simplifies this with the Image widget, especially when working with URLs. To display images from a URL, utilize the Image.network() constructor.

Image.network('https://blup.in/example.jpg'),

Additionally, Flutter's Image widget seamlessly supports animated gifs:

Image.network(
    'https://blup.in/assets/images/dash/dash-fainting.gif');

To achieve more advanced features like fading images after loading, the default Image.network constructor may not suffice. For such functionalities, explore the technique of "Fade in images with a placeholder.

Fade-In Image with Placeholder

When presenting images with the default Image widget, they often appear abruptly as they load, potentially disrupting the visual flow of your app. To enhance user experience, consider employing a placeholder that smoothly transitions into the loaded image. Enter the FadeInImage widget, designed precisely for this purpose.

FadeInImage seamlessly integrates with various image types, including in-memory, local assets, or internet-based, providing a smoother and more polished user experience.

In-Memory

In this example, utilize the transparent_image package to implement a straightforward transparent placeholder for in-memory images.

FadeInImage.memoryNetwork(
  placeholder: kTransparentImage,
  image: 'https://picsum.photos/250?image=9',
),

From asset bundle

Another option for placeholders is using local assets. Begin by adding the asset to the project's pubspec.yaml file as follows:

 flutter:
   assets:
+    - assets/loading.gif

Then, employ the FadeInImage.assetNetwork() constructor:

FadeInImage.assetNetwork(
  placeholder: 'assets/loading.gif',
  image: 'https://picsum.photos/250?image=9',
),

Playing and Pausing Videos

Video playback is a key feature in app development, and Flutter facilitates it with the video_player plugin. This plugin allows you to play videos from various sources like the file system, assets, or the internet.

It leverages AVPlayer on iOS and ExoPlayer on Android for playback.

Follow these steps to stream a video from the internet and implement basic play and pause controls:

  • Add the video_player dependency.

  • Grant necessary permissions to your app.

  • Create and initialize a VideoPlayerController.

  • Display the video player.

  • Implement play and pause functionality.

Add the video_player dependency

To incorporate video playback functionality, you'll need to add the video_player plugin as a dependency to your project. Simply execute the following command:

flutter pub add video_player

Add permissions to your app

Ensure your app has the necessary permissions to stream videos from the internet by updating your Android and iOS configurations.

Android: Add the following permission to the AndroidManifest.xml file located at <project root>/android/app/src/main/AndroidManifest.xm:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application ...>

    </application>

    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>

iOS: In the Info.plist file found at <project root>/ios/Runner/Info.plist, include the following:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
<

Create and Initialize a VideoPlayerController

With the video_player plugin installed and permissions set up, it's time to create and initialize a VideoPlayerController to handle video playback. Follow these steps to accomplish that:

  1. Create a StatefulWidget with a corresponding State class.

  2. Include variables in the State class to store the VideoPlayerController and the Future returned from VideoPlayerController.initialize.

  3. Initialize the controller in the initState method and dispose of it in the dispose method.

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

  @override
  State<VideoPlayerScreen> createState() => _VideoPlayerScreenState();
}

class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
  late VideoPlayerController _controller;
  late Future<void> _initializeVideoPlayerFuture;

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

    // Create and initialize the VideoPlayerController. 
    _controller = VideoPlayerController.network(
 'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4',
    );

    _initializeVideoPlayerFuture = _controller.initialize();
  }

  @override
  void dispose() {
    // Dispose of the VideoPlayerController to free up resources.
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // Complete the code in the next step.
    return Container();
  }
}

Display the video player

Now, let's display the video. Utilize the VideoPlayer widget provided by the video_player plugin to showcase the video initialized by the VideoPlayerController. To ensure the video maintains the correct aspect ratio, wrap the VideoPlayer widget in an AspectRatio widget.

Additionally, use a FutureBuilder to display a loading spinner while waiting for the VideoPlayerController to finish initializing. Remember, initializing the controller doesn't start playback.

FutureBuilder(
  future: _initializeVideoPlayerFuture,
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.done) {
      // Once the VideoPlayerController has finished initialization,
      // use its data to set the aspect ratio of the video.
      return AspectRatio(
        aspectRatio: _controller.value.aspectRatio,
        // Use the VideoPlayer widget to display the video.
        child: VideoPlayer(_controller),
      );
    } else {
      // While the VideoPlayerController is still initializing,
      // display a loading spinner.
      return const Center(
        child: CircularProgressIndicator(),
      );
    }
  },
)

Play and pause the video

To control video playback, use the play() and pause() method provided by the VideoPlayerController. By default, the video starts paused.

For this example, add a FloatingActionButton to toggle between play and pause states.

  FloatingActionButton(
  onPressed: () {
    // Toggle play/pause using setState to update UI.
    setState(() {
      if (_controller.value.isPlaying) {
        _controller.pause();
      } else {
        _controller.play();
      }
    });
  },
  // Display appropriate icon based on playback state.
  child: Icon(
    _controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
  ),
)

Flutter Assets & Images Practice Projects

Here are top 4 practice project tasks for students to enhance their understanding and implementation of assets and images in Flutter after reading the blog:

  1. Create a Gallery App:

    • Task: Develop a gallery app that displays images fetched from the internet and includes features such as image fade-in with placeholders.

    • Objective: Practice loading images dynamically, implementing fade-in effects, and handling network requests in Flutter.

  2. Build a Video Player App:

    • Task: Build a video player app that allows users to play and pause videos stored locally or fetched from the internet.

    • Objective: Implement video playback functionality, handle video assets, and integrate video controls in a Flutter app.

  3. Customize Image Transitions:

    • Task: Experiment with different image transition effects, such as slide, zoom, or blur, and implement them in a Flutter app.

    • Objective: Gain hands-on experience in customizing visual effects and enhancing user experience with animated image transitions.

  4. Create an Asset Management Tool:

    • Task: Develop a tool that allows users to manage assets in a Flutter project, including adding, deleting, and organizing assets.

    • Objective: Understand asset management in Flutter, practice working with asset bundles, and create a practical utility tool for Flutter developers.

Additional Resources for Further Learning:

Flutter Learning Resources

Looking to expand your knowledge further? Here are some valuable resources to deepen your understanding of assets and images in Flutter:

Official Flutter Documentation:

Recommended Tutorials and Articles:

Relevant Flutter Packages:

# Asset Management

# Image Handling

Resources:

Download Our Flutter-based App Builder "Blup"

Experience the Benefits of BLUP - Your Low-Code Flutter App Builder!

Start Building with Blup - Blup's Role in App Development

Unlock the Potential:

  • Efficiency: Build Flutter apps faster with our intuitive drag-and-drop interface, reducing development time and effort.

  • Cost-Effective: Save on development costs by leveraging BLUP's low-code capabilities, eliminating the need for extensive coding expertise.

  • Scalability: Seamlessly scale your apps as your business grows, with BLUP's flexible architecture and easy customization options.

Conclusion

In wrapping up our exploration of assets and images in Flutter app development, let's recap the key concepts covered and emphasize their significance in enhancing both the visual appeal and functionality of your applications.

Recap:

  • Explored dynamic loading, transitions, and asset management.

  • These techniques empower immersive experiences like galleries and games.

Importance:

  • Assets and images are vital for captivating users and conveying information effectively.

Encouragement:

  • Keep experimenting and pushing boundaries in your Flutter journey.

Top Blogs

Follow us on

Follow us on