How To Manage E-Commerce App Development With Flutter?

Quokka Labs
9 min readFeb 13, 2023

Flutter is a trending open-source framework that provides a single codebase for building exclusive apps. It is versatile enough and extends the SDK’s support to compile the native apps for web, mobile, and desktop. From MVPs to prototyping and cross-platform development, flutter offers bucketful opportunities for developers.

Whether a startup or a small/ large enterprise, flutter can fit in with their goals. The pace, flexibility, rich features, and affordability make flutter the perfect choice for e-commerce app development.

How to build an e-commerce app using Flutter?

Just like eCommerce websites, e-commerce apps also set the business on fire. It eases the accessibility to shopping the products more conveniently.

Here in this blog, we will guide you through the e-commerce app development project.

While we are heading on the path of flutter app development, take advantage of the following features to integrate.

  • Product Gallery:

It would be best if you built this section on priority to showcase the products you are selling.

  • Shipping/ Delivery Details:

Shipping and delivery details are mandatory for online shopping. Incomplete information will disrupt the orders.

  • Shopping cart

We always carry a bag in offline shopping where we keep all the stuff. The shopping cart is the same. It records which products are added, removed, edited, or deleted from the cart. Subsequently, it keeps a record of in-cart items.

  • Payment gateway

An eCommerce app will be of no use without integrating the payment gateway. You can choose Google Pay, Phonepay, PayPal, Stripe, or any other payment gateway.

  • Reviews & rating integration

Reviews and ratings impact the user’s shopping experience. They know if the people are interested in the products or not. You can integrate the flutter widgets to display reviews and ratings.

Beyond all, you need to spend the effort on the app’s user experience. Let’s trail an amazing ride of flutter app development. Get to know about the material motion, search and toggle action to achieve an intuitive UX.

8 Steps To Initiate E-Commerce App Development With Flutter

You know what to do to build an eCommerce app. Still, we also want to learn how to accomplish the flutter e-commerce app development. Below, you will get the answer to all the questions mentioned below:

  • Product Initialization
  • Launch Screen for different purposes: Product listing, Product details, cart
  • How to add the products?
  • How to Build the cart?
  • How to make it responsive?
  • How to add a Toggle View?
  • How to add a search feature?
  • How do you launch animations?

Product Initialization

  • To initiate the projects, launch the flutter SDK. It is the most basic project requirement.

You can confirm the installation with a single action in the terminal:

Flutter Doctor

Note that: there should be no red flag occurrence.

  • Launch the directory where you will launch the project. Next, you need to install the IDE for further processing. Run this command to add to the specified directory.

Flutter create ecomm_app

  • You have multiple options for IDE to work on the flutter app projects. Android Studio, Visual Studio Code Editor, Emac, Codemagic, etc., are some of the top preferences.
flutter run
// Tip: If you are running multiple devices, you can run the
// following:
flutter run -d "<device_name>"

Next, we need to launch screens to manage different accessibilities.

Generally, we navigate to the app screen and see multiple products. Then we hit on anyone as per our interest. Further, we decided to cart in and navigate to ship an order.

We need a screen to display all products with name, image and best price. Also, we will add the toggle to set the view type as grid or list. So, there will be an AppBar, TextFormField, IconButton, gridView, and container.

You can insert the following code into your IDE.

Container(
//width: MediaQuery.of(context).size.width * 0.45,
decoration: BoxDecoration(
color: AppTheme.of(context).secondaryBackground,
boxShadow: [
BoxShadow(
blurRadius: 4,
color: Color(0x3600000F),
offset: Offset(0, 2),
)
],
borderRadius: BorderRadius.circular(8),
),
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 12),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Row(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: ClipRRect(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(0),
bottomRight: Radius.circular(0),
topLeft: Radius.circular(8),
topRight: Radius.circular(8),
),
child: Image.network(
product.image,
width: 100,
height: 100,
fit: BoxFit.cover,
),
),
),
],
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 4, 0, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: EdgeInsetsDirectional.fromSTEB(8, 4, 0, 0),
child: Text(
product.name,
style: AppTheme.of(context).bodyText1,
),
),
],
),
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 2, 0, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: EdgeInsetsDirectional.fromSTEB(8, 4, 0, 0),
child: Text(
'\$${product.price}',
style: AppTheme.of(context).bodyText2,
),
),
],
),
),
],
),
),
);
  • Now, we need to design the product details page. We will launch some widgets. You can display the product quantity, in-cart status, and other accessibility. Try the badge widget for the product details page.
Container(
//width: MediaQuery.of(context).size.width * 0.45,
decoration: BoxDecoration(
color: AppTheme.of(context).secondaryBackground,
boxShadow: [
BoxShadow(
blurRadius: 4,
color: Color(0x3600000F),
offset: Offset(0, 2),
)
],
borderRadius: BorderRadius.circular(8),
),
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 12),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Row(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: ClipRRect(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(0),
bottomRight: Radius.circular(0),
topLeft: Radius.circular(8),
topRight: Radius.circular(8),
),
child: Image.network(
product.image,
width: 100,
height: 100,
fit: BoxFit.cover,
),
),
),
],
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 4, 0, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: EdgeInsetsDirectional.fromSTEB(8, 4, 0, 0),
child: Text(
product.name,
style: AppTheme.of(context).bodyText1,
),
),
],
),
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 2, 0, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
children: [
Padding(
padding: EdgeInsetsDirectional.fromSTEB(8, 4, 0, 0),
child: Text(
'\$${product.price}',
style: AppTheme.of(context).bodyText2,
),
),
],
),
),
],
),
),
);

We need to design another page for cart accessibility. It will mention the pricing summary and check out related options. There will be the container, text, and button. Insert the following code to display product items in the cart section. We will do this list view builder.

ListView.builder(
padding: EdgeInsets.zero,
primary: false,
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: cartItems.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: EdgeInsetsDirectional.fromSTEB(16, 8, 16, 0),
child: Container(
width: double.infinity,
height: 100,
decoration: BoxDecoration(
color: AppTheme.of(context).secondaryBackground,
boxShadow: [
BoxShadow(
blurRadius: 4,
color: Color(0x320E151B),
offset: Offset(0, 1),
)
],
borderRadius: BorderRadius.circular(12),
),
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(16, 8, 8, 8),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Hero(
tag: 'ControllerImage',
transitionOnUserGestures: true,
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Image.network(
cartItems[index].image,
width: 80,
height: 80,
fit: BoxFit.fitWidth,
),
),
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(12, 0, 0, 0),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 8),
child: Text(
cartItems[index].name,
style: AppTheme.of(context).subtitle2.override(
fontFamily: 'Poppins',
color: AppTheme.of(context).primaryText,
),
),
),
Text(
'\$${cartItems[index].price}',
style: AppTheme.of(context).bodyText2,
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 8, 0, 0),
child: Text(
'Quanity: ${cartItems[index].quantity}',
style: AppTheme.of(context).bodyText2,
),
),
],
),
),
IconButton(
icon: Icon(
Icons.delete_outline_rounded,
color: Color(0xFFE86969),
size: 20,
),
onPressed: () {
// Remove item
},
),
],
),
),
),
);
});

How to add products?

We have completed the UI part. Now we need to add more products so our users can add to carts and order. These activities are managed from the backend server. Here, we will not do some out-of-the-box things. We will do this with a variable. First, we will create a product class and mention different fields to carry different values. So, there will be five fields ID, name, image, price, and quantity.

class Product {
final int id;
final String name;
final String image;
final double price;
int quantity;

Product({required this.id, required this.name, required this.image, required this.price, this.quantity = 0});
}

Follow this to prepare a product list.

final List<Product> products = [
Product(
id: 1,
name: 'Champion',
image:
'https://images.unsplash.com/photo-1606107557195-0e29a4b5b4aa?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=764&q=80',
price: 55.5),
Product(
id: 2,
name: 'Stark',
image:
'https://images.unsplash.com/photo-1549298916-b41d501d3772?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1624&q=80',
price: 65.5),

];

We will do the same for the grid view.

GridView.builder(
itemCount: products.length,
itemBuilder: (context, index) => ProductTile(
itemNo: index,
product: products[index],
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 1,
),
)

How to build the cart?

To make the purchase, we need a cart where we can keep our items virtually. We need to launch an ideal state to manage this activity. Let’s initiate the Bloc design pattern to practice the state management technique. After implementing this, we can perform the add and remove items actions.

CartBloc

There will be three classes name ad bloc, event, and state the business logic.

class CartBloc extends Bloc<CartEvent, CartState> {
CartBloc() : super(ProductAdded(cartItem: []));

final List<Product> _cartItems = [];
List<Product> get items => _cartItems;
bool isGridView = true;

@override
Stream<CartState> mapEventToState(CartEvent event) async* {
if (event is AddProduct) {
_cartItems.add(event.productIndex);
yield ProductAdded(cartItem: _cartItems);
} else if (event is RemoveProduct) {
_cartItems.remove(event.productIndex);
yield ProductRemoved(cartItem: _cartItems);
} else if (event is ChangeGallaryView) {
isGridView = event.isGridView;
yield ChangeGallaryViewState(isGridView: isGridView);
}
}
}

CartEvent- to manage the flow to cart bloc (to send items)

abstract class CartEvent extends Equatable {
const CartEvent();

@override
List<Object> get props => [];
}

class AddProduct extends CartEvent {
final Product productIndex;

const AddProduct(this.productIndex);

@override
List<Object> get props => [productIndex];

@override
String toString() => 'AddProduct { index: $productIndex }';
}

class RemoveProduct extends CartEvent {
final Product productIndex;

const RemoveProduct(this.productIndex);

@override
List<Object> get props => [productIndex];

@override
String toString() => 'RemoveProduct { index: $productIndex }';
}

CartState

This will manage the flow to the UI side.

abstract class CartState {
final List<Product> cartItem;
final bool isGridView;
const CartState({this.cartItem = const [], this.isGridView = true});

@override
List<Object> get props => [];
}

class CartLoadInProgress extends CartState {
CartLoadInProgress({required super.cartItem});
}

class ProductAdded extends CartState {
final List<Product> cartItem;

const ProductAdded({required this.cartItem}) : super(cartItem: cartItem);

@override
List<Object> get props => [cartItem];

@override
String toString() => 'ProductAdded { todos: $cartItem }';
}

You need to launch the button event to add the items. We will do this on UI with a ‘Add to Cart’ button. You can manage this add-to-cart action like this.

onPressed: () {
Product p = widget.product;
p.quantity = countControllerValue!.toInt();
BlocProvider.of<CartBloc>(context).add(AddProduct(p));
}

We want to do the same for removing the things from the cart.

onPressed: () {
BlocProvider.of<CartBloc>(context).add(RemoveProduct(cartItems[index]));
}

You know the cart gets updated after performing every add or remove item action. Let’s accomplish the action in our app.

BlocBuilder<CartBloc, CartState>(builder: (_, cartState) {
return ListView.builder();
}),

Adding some responsiveness and delivering your users a more intuitive experience would be excellent. With the web version, your users can see a few more items. By doing some modifications in the code, you can deliver a native app experience.

return LayoutBuilder(builder: (context, constraints) {
return GridView.builder(
itemCount: products.length,
itemBuilder: (context, index) => ProductTileAnimation(
itemNo: index,
product: products[index],
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: constraints.maxWidth > 700 ? 4 : 2, //<-SEE HERE
childAspectRatio: 1,
),
);
});

Modify the heights and width for GridView. You need to apply some constraints and then launch the user interface of your product preferences.

Add the toggle to shift the view from the list to the grid. Adding the boolean variable will let you change the icon.

BlocBuilder<CartBloc, CartState>(builder: (_, cartState) {
bool isGridView = cartState.isGridView;
return IconButton(
onPressed: () {
BlocProvider.of<CartBloc>(context).add(ChangeGallaryView(!isGridView));
},
icon: !isGridView ? Icon(Icons.grid_on) : Icon(Icons.list));
})

Here is the code to display your product view list.

BlocBuilder<CartBloc, CartState>(builder: (_, cartState) {
bool isGridView = cartState.isGridView;
if (isGridView) {
return LayoutBuilder(builder: (context, constraints) {
return GridView.builder(
itemCount: products.length,
itemBuilder: (context, index) => ProductTile(
itemNo: index,
product: products[index],
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 1,
),
);
});
} else {
return ListView.builder(
itemCount: products.length,
itemBuilder: (BuildContext context, int index) {
return ProductTile(
itemNo: index,
product: products[index],
);
});
}
});

Code to Search for the product from the gallery. Learn about the implementation of an onChnaged event.

TextFormField(
controller: textController,
obscureText: false,
onChanged: (_) => EasyDebounce.debounce(
'tFMemberController',
Duration(milliseconds: 0),
() {
isSearchStarted =
textController!.text.isNotEmpty && textController!.text.trim().length > 0;
if (isSearchStarted) {
print('${textController!.text.trim()}');
searchedProducts = products
.where((item) =>
item.name.toLowerCase().contains(textController!.text.trim().toLowerCase()))
.toList();
}
setState(() {});
},
),
)

Implement the isSearchStarted variable to confirm the search results:

ProductList(
products: isSearchStarted ? searchedProducts : products,
)

How to Launch Animation?

ContainerTransitionType _transitionType = ContainerTransitionType.fade;
OpenContainer<bool>(
transitionType: _transitionType,
openBuilder: (BuildContext _, VoidCallback openContainer) {
return ProductDetailWidget(
product: product,
);
},
closedShape: const RoundedRectangleBorder(),
closedElevation: 0.0,
closedBuilder: (BuildContext _, VoidCallback openContainer) {
return Container(
// Product tile
);
},
)

Wrapup:

We recommend you to add on the thing as mentioned earlier. Please pay special attention to screens to deliver an intuitive user experience. Moreover, if you are targeting a wide base of users, integrate the admin panel. You can go the extra mile and add an ML AI model to automate promotional content for user interest. It will drive efficiency in your ecommerce flutter app development project. We have asked you to add the best suitable payment gateway. So the goal can easily be accomplished, and users can easily purchase.

--

--

Quokka Labs

Quokka Labs is a Web/Mobile App Development Company in India. Founded by a team of Technology enthusiasts, our goal is to create digital products of the highest