Flutter E Commerce App Design -Section 13

In this section, we will take a look at the design part of the e-commerce app. UI or design plays an important role in building Flutter apps. 

In the previous section we have added a Cart Model. However, to nest a new Provider model class, we need to use the multi provider property of the Provider package.

Although before we have learned how we can use a nested provider to enhance the performance of our E-Commerce app. Right? 

Yet, just to recapitulate we will show how the advantage of the nested provider in Flutter works.To make it happen we have changed our app entry point, that is the main dart file.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:dynamic_color/dynamic_color.dart';
import 'models/cart_model.dart';
import 'models/theme.dart';

import 'models/products.dart';
import 'views/cart_page.dart';
import 'views/product_detail_screen.dart';
import 'views/products_overview_screen.dart';

final settings = ValueNotifier(
  ThemeSettings(
    sourceColor: const Color.fromARGB(255, 240, 10, 182),
    themeMode: ThemeMode.system,
  ),
);

/// creating a new branch adding cart
///
///
void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (_) => Products(),
        ),
        ChangeNotifierProvider(
          create: (context) => CartModel(),
        )
      ],
      child: DynamicColorBuilder(
        builder: (lightDynamic, darkDynamic) => ThemeProvider(
          lightDynamic: lightDynamic,
          darkDynamic: darkDynamic,
          settings: settings,
          child: const MyApp(),
        ),
      ),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final theme = ThemeProvider.of(context);
    return MaterialApp(
      title: 'E Commerce App',
      debugShowCheckedModeBanner: false,
      theme: theme.light(settings.value.sourceColor),
      home: const ProductsOverviewScreen(),
      routes: {
        ProductDetailScreen.routeName: (ctx) => const ProductDetailScreen(),
        CartScreen.routeName: (ctx) => const CartScreen(),
      },
    );
  }
}

Previously, we needed one provider. As a result, we didn’t need the multi provider concept. 

However, once we have to integrate and provide more than one Model class, we need the multi provider.

That’s the first point.

Secondly, we need a separate Cart page. As a result, users can go to the Cart page to complete the order.

In our previous section we had seen why we used ChangeNotifierProvider value constructor. However, at the same time, we used Provider Consumer in our Product Item controller. 

For Cart Model class, we have followed the same technique.

As a result, in the product overview page, we have used Provider.of and Consumer at the same time.

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

import '../controllers/cart_design_controller.dart';
import '../controllers/products_grid.dart';
import '../models/cart_model.dart';
import 'cart_page.dart';

enum FilterOptions {
  favorites,
  all,
}

class ProductsOverviewScreen extends StatefulWidget {
  const ProductsOverviewScreen({Key? key}) : super(key: key);
  @override
  State<ProductsOverviewScreen> createState() => _ProductsOverviewScreenState();
}

class _ProductsOverviewScreenState extends State<ProductsOverviewScreen> {
  var _showOnlyFavorites = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('E Commerce App'),
        actions: <Widget>[
          PopupMenuButton(
            onSelected: (FilterOptions selectedValue) {
              setState(() {
                if (selectedValue == FilterOptions.favorites) {
                  _showOnlyFavorites = true;
                } else {
                  _showOnlyFavorites = false;
                }
              });
            },
            icon: const Icon(
              Icons.more_vert,
            ),
            itemBuilder: (_) => [
              const PopupMenuItem(
                value: FilterOptions.favorites,
                child: Text('Only Favorites'),
              ),
              const PopupMenuItem(
                value: FilterOptions.all,
                child: Text('Show All'),
              ),
            ],
          ),
          Consumer<CartModel>(
            builder: (_, cart, child) => CartDesignController(
              value: cart.itemCount.toString(),
              color: Theme.of(context).colorScheme.background,
              child: child,
            ),
            child: IconButton(
              icon: const Icon(
                Icons.shopping_cart,
              ),
              onPressed: () {
                Navigator.of(context).pushNamed(CartScreen.routeName);
              },
            ),
          ),
        ],
      ),
      body: ProductsGrid(_showOnlyFavorites),
    );
  }
}

How to design the Cart in Flutter E Commerce App

In the above code, we have seen a few things that we need to explain first.

We don’t need to explain again why we have used Provider.of and Consumer at the same time. Because we’ve discussed it before.

The icon button widget can display an icon, and besides users can press it to reach the Cart page to complete the order.

We will discuss later how we can design the Cart page in a separate section.

Our main challenge is to design the Cart in the AppBar so that once users press the Cart icon the number changes.

Finally pressing the Cart icon in the AppBar, user can see her own Cart.

Cart design in E-Commerce App
Cart design in E-Commerce App

On the top right corner, just above the Cart Icon it displays the number 5. 

That means the user has added 5 items to her cart. 

But how did we design it?

To understand that, we can take a look at the following code. We have designed this widget and placed it in our controller folder.

import 'package:flutter/material.dart';

class CartDesignController extends StatelessWidget {
  const CartDesignController({
    Key? key,
    required this.child,
    required this.value,
    required this.color,
  }) : super(key: key);

  final Widget? child;
  final String value;
  final Color color;

  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: Alignment.center,
      children: [
        child!,
        Positioned(
          right: 8,
          top: 8,
          child: Container(
            padding: const EdgeInsets.all(2.0),
            // color: Theme.of(context).accentColor,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(10.0),
              color: color,
            ),
            constraints: const BoxConstraints(
              minWidth: 16,
              minHeight: 16,
            ),
            child: Text(
              value,
              textAlign: TextAlign.center,
              style: const TextStyle(
                fontSize: 10,
              ),
            ),
          ),
        )
      ],
    );
  }
}

The concept is simple.

Because we have used a Stack widget, where on the top, we have placed a Child Widget.

Later this child widget will be a Cart Icon, which will also act as a button to navigate to the Cart page.

However, on the top of this Icon Button, we have used a Positioned widget that reflects the number of the added product items.

The greatest advantage of Flutter is we can use the Front end design and make our UI as beautiful and useful as we want to.

There are lots of widgets. All we need to do is to place them and use them the right way.

In our next discussion we will see how we can navigate to the Cart page.

What Next?

Books at Leanpub

Books in Apress

My books at Amazon

Courses at Educative

GitHub repository

Python and Data Science

Twitter

Comments

Leave a Reply