Flutter packages are a powerful way to share and reuse code in your Flutter projects. Whether you want to contribute to the Flutter community or streamline your Flutter app development process, creating Flutter packages is the key. 

How to Create Packages for Flutter

In this post, I will take you through the process of creating Flutter packages, from setting up your development environment to publishing your package on Dart’s package repository, pub.dev. Whether you’re a seasoned Flutter developer looking to share your expertise or a newcomer eager to contribute to the Flutter community, this post will walk you through the steps to package your Flutter code effectively.

About Flutter Package

A Flutter Package is a broader term that refers to any self-contained piece of code that can be imported and used in a Flutter project. Packages can contain widgets, utility functions, plugins, or any other code that can be reused across multiple Flutter projects. 

Advantages of creating packages:

Flutter packages are a cornerstone of the Flutter framework, offering developers a wide array of benefits that significantly streamline development and boost productivity. 

Reusability: By creating packages, you enable the reuse of code across multiple projects. This is particularly useful for sharing common functionalities or maintaining a consistent design language across different apps. This helps save time because you don’t have to recreate the same things over and over.

Decoupling: Packages can be developed in a way that they are decoupled from the specific app’s context. This makes it easier to replace or update individual components without affecting the entire application.

Code Sharing: Developers within your organization can easily share packages among different projects, leading to faster development cycles and reduced duplication of effort.

Focused Development: Package development allows teams to focus on specific modules without being overwhelmed by the entire application’s codebase.

Versioning and Updates: Packages can have their own versioning and update cycles, which can be beneficial when different parts of the application evolve at different rates.

Maintenance: If a module requires updates or fixes, you can address them within the context of the package without affecting the rest of the application.

Now, let’s get started with a step-by-step practical guide on how to create packages for Flutter. 

Step 1: Create a Flutter Package

To create a Flutter package, go to your command line interface and directory where you want to create the Flutter package and run the command mentioned below:

flutter create --template=package mi_flutter_package

Replace mi_flutter_package with the desired name for your package.

This command will create a Flutter package project with the mi_flutter_package folder below the mentioned folder structure.

package_name/
├── lib/
│   └── mi_flutter_package.dart
├── pubspec.yaml
├── README.md
└── example/
    ├── lib/
    └── …

LICENSE

This file is mostly blank and is meant for adding legal terms regarding package usage.

test/mi_flutter_package_test.dart

The unit tests for the package.

mi_flutter_package.iml

A configuration file used by the IntelliJ IDEs.

.gitignore

 A hidden file that tells Git what files or folders it should ignore when tracking changes in a project.

.metadata

A hidden file is used by IDEs to track the properties of the Flutter project.

Pubspec.yaml

A YAML file containing metadata that specifies the package’s dependencies. Used by the pub tool.

README.md

A markdown file that briefly describes the package’s purpose and its usage.

Step 2: Implementing Your Package

We need to write the code for our package inside the lib folder. This is where you’ll define your package’s classes, functions, widgets, or other functionality.

In our package, we will add a class to define a flexible custom app bar widget named MIAppBarWidget for Flutter applications. Developers can use this widget and customize various aspects of the app bar’s appearance and behavior by providing values through the constructor parameters. This allows for greater flexibility in designing the app’s user interface.

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


class MIAppBarWidget extends StatelessWidget implements PreferredSizeWidget {
 final Widget? leading;
 final double? leadingWidth;
 final bool automaticallyImplyLeading;
 final Widget title;
 final Function(BuildContext context) onBackButtonTapped;
 final TextStyle? titleTextStyle;
 final List<Widget>? actions;
 final bool centerTitle;
 final double toolbarHeight;
 final double toolbarOpacity;
 final ShapeBorder? shapeBorder;
 final double? elevation;
 final Color? backgroundColor;
 final IconThemeData? actionsIconTheme;
 final Color? shadowColor;
 final double sideMargin;
 final Color? statusBarColor;
 final Gradient? gradient;
 final BorderRadiusGeometry? gradientRadius;


 const MIAppBarWidget(
     {Key? key,
     this.leading,
     this.automaticallyImplyLeading = false,
     required this.onBackButtonTapped,
     required this.title,
     this.titleTextStyle,
     this.actions,
     this.centerTitle = false,
     this.toolbarHeight = 60,
     this.toolbarOpacity = 1,
     this.shapeBorder,
     this.elevation = 8,
     this.backgroundColor,
     this.leadingWidth = 56,
     this.actionsIconTheme =
         const IconThemeData(color: Colors.black, size: 36),
     this.shadowColor,
     this.sideMargin = 0,
     this.gradient,
     this.gradientRadius,
     this.statusBarColor})
     : super(key: key);


 @override
 Widget build(BuildContext context) {
   return Container(
     margin: EdgeInsets.only(left: sideMargin, right: sideMargin),
     child: Center(
       child: AppBar(
           leading: InkWell(
             onTap: () => {onBackButtonTapped(context)},
             child: leading,
           ),
           flexibleSpace: Container(
               decoration: BoxDecoration(
                   gradient: gradient, borderRadius: gradientRadius)),
           leadingWidth: leadingWidth,
           iconTheme: actionsIconTheme,
           automaticallyImplyLeading: automaticallyImplyLeading,
           title: title,
           titleTextStyle: titleTextStyle,
           centerTitle: centerTitle,
           actions: actions,
           actionsIconTheme: actionsIconTheme,
           elevation: elevation,
           toolbarHeight: toolbarHeight,
           toolbarOpacity: toolbarOpacity,
           backgroundColor: backgroundColor,
           shadowColor: shadowColor,
           systemOverlayStyle: SystemUiOverlayStyle(
             statusBarColor: statusBarColor, // Status bar only for android.
           ),
           shape: shapeBorder),
     ),
   );
 }


 @override
 Size get preferredSize => Size.fromHeight(toolbarHeight);
}
Code language: PHP (php)

Make sure you add the export ‘mi_app_bar_widget.dart’; line in your mi_flutter_package.dart file. By doing this you will make the contents of the specified file (mi_app_bar_widget.dart in this case) available for use in other parts of your application.

export 'mi_app_bar_widget.dart';Code language: JavaScript (javascript)

Important: When developing custom widgets within your package, ensure that you export these files. This action enables other applications utilizing your package to access and use these custom widgets.

How to Add Screens Designed in Flutter into Your Native App

Step 3: Adding Example Application to Our Package

To create an Example application within your package, go to your command line interface and root project folder and run the command mentioned below:

flutter create example

This command will create a Flutter example app within your package folder.

Step 4: Using MIAppBarWidget in the Example App

– Add this package to your example app, go to your pubspec.yaml file under example app add mi_flutter_package under dependencies.

  • If you’re using the terminal, execute the command `flutter pub get`.
  • In VS Code, simply click on “Get Packages” found on the right side of the action ribbon at the top of your `pubspec.yaml` file. This is represented by a Download icon.
  • If you’re working in Android Studio/IntelliJ, navigate to the action ribbon at the top of your `pubspec.yaml` file and select “Pub get” to retrieve the necessary packages.
dependencies:
  flutter:
    sdk: flutter
  mi_flutter_package:
    path: ../

Add MIAppWidget in your example app. Here is how our updated AppBar code looks like –

Scaffold(
    appBar: MIAppBarWidget(
      automaticallyImplyLeading: true,
      title: const Text(
        "MI AppBar",
        style: TextStyle(color: Colors.white),
      ),
      toolbarHeight: 56,
      leadingWidth: 50,
      centerTitle: true,
      backgroundColor: Colors.blue,
      statusBarColor: Colors.blueGrey,
      elevation: 10,
      shadowColor: Colors.black,
      //sideMargin: 10,
      shapeBorder: const RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
          bottomRight: Radius.circular(10),
          bottomLeft: Radius.circular(10),
        ),
      ),
      onBackButtonTapped: (BuildContext context) {},
    ),
  );
Code language: JavaScript (javascript)

Step 5: Running Example App in iOS/Android Simulator/Emulator

If you can’t see any simulator or emulator option to run your code in Android Studio, Please follow the steps mentioned below.

  • Click on Add Configuration -> Add New Configuration -> Fluter
  • Enter ‘Name’ as main
  • For Dart Entrypoint -> Select the path of the main.dart file in your example app
  • Click on Apply and press Ok
Running Example App

We’re all set! You can now run the application and Voila!

Simulator

We have now successfully integrated mi_flutter_package in our example application.

Step 6: Using your Flutter Package in Other Applications

Adding mi_flutter_package locally in your other flutter applications:

For adding  mi_flutter_package to your application, Go to your application’s pubsec.yaml file and add it under dependencies.

mi_flutter_package:
path: /Users/../mi_flutter_package
Code language: JavaScript (javascript)

Above, mi_flutter_package is defined as a dependency in a pubspec.yaml file. It’s specified as a local dependency, which means that the package will be fetched from the local path located at the provided path (/Users/../mi_flutter_package)

Adding mi_flutter_package in your flutter applications via private Git Repository:

For adding  mi_flutter_package to your application, Go to your application’s pubsec.yaml file and add it under dependencies.

mi_flutter_package:
  git:
    url: git@gitlab.com:flutter_package/miflutterpackage.git
    ref: main

Above, mi_flutter_package is defined as a dependency in a pubspec.yaml file. It’s specified as a Git dependency, which means that the package will be fetched from the Git repository located at the provided URL (git@gitlab.com:flutter_package/miflutterpackage.git). The ref property specifies the branch or commit reference (in this case, main) to use from the Git repository. This allows the Flutter project to pull in the code and assets from the specified Git repository and use them within the project.

Step 7: Publish your Package to pub.dev

To publish your package on pub.dev, you’ll need to use the pub command-line tool, which is the Dart package manager. 

Open your terminal and navigate to your package’s directory.

– Login to Pub.dev:

Before you can publish, you need to authenticate with your pub.dev account using the following command:

pub login

Follow the prompts to log in with your Dart/Google account.

– Publish Your Package: To publish your package, use the following command:

pub publish –dry-run

The –dry-run flag allows you to check if your package can be successfully published without actually publishing it. It’s a good practice to use this flag first to catch any issues. If the dry run is successful, remove the –dry-run flag and publish your package:

pub publish

Verify the Publish: After publishing, visit pub.dev to make sure your package is listed correctly. You can search for your package by name to find it.

Note: Make sure your `pubspec.yaml` file is correctly filled out. It should include essential information about your package, such as name, version, description, author, and dependencies.

Summing It Up

I hope you enjoyed this tutorial on Creating Packages for Flutter. To download the code for this app, please click here.

Flutter packages are essential tools for developers, fostering collaboration and efficiency. With this guide, you’re now well-prepared to create and use packages effectively. By sharing your code or leveraging existing packages, you can streamline your Flutter development process and deliver an intuitive user experience. If you have any questions or feedback, don’t hesitate to reach out. We’re here to help you enhance the performance of your Flutter app.

Author's Bio

Prashant Telangi
Prashant Telangi

Prashant Telangi brings over 14 years of experience in Mobile Technology, He is currently serving as Technical Architect - Mobility at Mobisoft Infotech. With a proven history in IT and services, he is a skilled, passionate developer specializing in Mobile Applications. His strong engineering background underscores his commitment to crafting innovative solutions in the ever-evolving tech landscape.