Creating a Dynamic Product List View in Flutter with GetX

An eCommerce product page created in Flutter should provide a clear and comprehensive description of the product being sold to potential buyers. Here are some key elements that should be included on the product page:

product_list_view

  • Product Images: Display high-quality images of the product from different angles and perspectives. This allows the buyer to better understand the product and make an informed decision.
  • Product Description: Provide a detailed and accurate description of the product, including its features, benefits, and specifications. This information should be presented in a clear and easy-to-read format, using bullet points or short paragraphs.
  • Product Reviews: Include customer reviews and ratings of the product to help potential buyers make a more informed decision. Make sure to allow buyers to leave reviews and ratings on your website.
  • Pricing and Discounts: Clearly display the product's price, any discounts or promotions that may be available, and any applicable taxes or shipping costs.

By including these key elements, you can create a comprehensive and user-friendly eCommerce product page in Flutter that helps potential buyers make an informed purchasing decision.

shopping_controller.dart

This is a Flutter controller class that manages a list of products. It uses the GetX package to manage the state of the products list, making it observable so that any changes to it will automatically trigger a rebuild of the UI.

The controller fetches a list of dummy products using a simulated delay of one second, and then sets the value of the products observable to the result.

The findById method takes an id parameter and returns the first product in the products list whose id matches the provided value.

This code assumes that a Product model class has been defined elsewhere in the codebase.

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

import '../model/product.dart';

class ShoppingController extends GetxController {
  var products = <Product>[].obs;

  @override
  void onInit() {
    super.onInit();
    fetchProducts();
  }

  void fetchProducts() async {
    await Future.delayed(Duration(seconds: 1));
    var productResult = [
      Product(
          id: 1,
          price: 30,
          productDescription:
              'Your perfect pack for everyday use and walks in the forest. Stash your laptop (up to 15 inches) in the padded sleeve, your everyday',
          productImage:
              'https://fakestoreapi.com/img/81fPKd-2AYL._AC_SL1500_.jpg',
          productName: 'Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops',
          color: Colors.blueGrey),
      Product(
          id: 2,
          price: 40,
          productDescription:
              'Slim-fitting style, contrast raglan long sleeve, three-button henley placket, light weight & soft fabric for breathable and comfortable wearing.',
          productImage:
              'https://fakestoreapi.com/img/71-3HjGNDUL._AC_SY879._SX._UX._SY._UY_.jpg',
          productName: 'Mens Casual Premium Slim Fit T-Shirts',
          color: Colors.black),
      Product(
          id: 3,
          price: 49.5,
          productDescription:
              'great outerwear jackets for Spring/Autumn/Winter, suitable for many occasions, such as working, hiking, camping, mountain/rock climbing, cycling, traveling or other outdoors.',
          productImage:
              'https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg',
          productName: 'Mens Cotton Jacket',
          color: Colors.brown),
      Product(
          id: 4,
          price: 30,
          productDescription:
              'Your perfect pack for everyday use and walks in the forest. Stash your laptop (up to 15 inches) in the padded sleeve, your everyday',
          productImage:
              'https://fakestoreapi.com/img/81fPKd-2AYL._AC_SL1500_.jpg',
          productName: 'Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops',
          color: Colors.blueGrey),
      Product(
          id: 5,
          price: 40,
          productDescription:
              'Slim-fitting style, contrast raglan long sleeve, three-button henley placket, light weight & soft fabric for breathable and comfortable wearing.',
          productImage:
              'https://fakestoreapi.com/img/71-3HjGNDUL._AC_SY879._SX._UX._SY._UY_.jpg',
          productName: 'Mens Casual Premium Slim Fit T-Shirts',
          color: Colors.black),
      Product(
          id: 6,
          price: 49.5,
          productDescription:
              'great outerwear jackets for Spring/Autumn/Winter, suitable for many occasions, such as working, hiking, camping, mountain/rock climbing, cycling, traveling or other outdoors.',
          productImage:
              'https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg',
          productName: 'Mens Cotton Jacket',
          color: Colors.brown),
    ];
    products.value = productResult;
  }

  Product findById(int id) {
    return products.firstWhere((product) => product.id == id);
  }
}

product.dart

This is a Flutter model class that represents a product. It has several properties that describe the product, including:
  • id: An integer that uniquely identifies the product.
  • productName: A string that represents the name of the product.
  • productImage: A string that represents the URL of the product image.
  • productDescription: A string that provides a description of the product.
  • price: A double that represents the price of the product.
  • color: A Color object that represents the color of the product.
  • The Product class has a named constructor that takes all the properties as named parameters and makes them required using the required keyword.
This code assumes that the Color class is imported from the flutter/widgets.dart package.

import 'package:flutter/widgets.dart';

class Product {
  final int id;
  final String productName;
  final String productImage;
  final String productDescription;
  final double price;
  final Color color;

  Product({
    required this.id,
    required this.productName,
    required this.productImage,
    required this.productDescription,
    required this.price,
    required this.color,
  });
}

grid_view.dart

This code defines a StatefulWidget called GridViewOverView that displays a grid view of product items. Each item is represented as a row with a product image, title, content, rating, and price.

The GridViewOverView widget takes in several required parameters including id, title, content, color, image, and price for each product item. These parameters are used to construct a Product object.

The build method of the GridViewOverViewState class returns a GestureDetector widget that displays the product details page when the user taps on the product row. The product details page is implemented using Get.toNamed to navigate to the ProductDetailPage passing the widget.id as an argument.

The row is made up of three main sections:
  1. A colored container on the left side of the row that serves as a visual cue for the product color.
  2. The product title, content, and rating displayed in a column.
  3. The product image displayed on the right side of the row, inside a Stack widget that allows for the image to overlap the colored container.
The product rating is represented using a row of five Icon widgets, where the first three icons are solid orange stars, and the last two icons are empty stars.

Finally, the product price is displayed at the bottom of the column.

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

import '../product_detail_page.dart';

class GridViewOverView extends StatefulWidget {
  int id;
  String title;
  String content;
  Color color;
  String image;
  double price;

  GridViewOverView(
      {required this.id,
      required this.title,
      required this.content,
      required this.color,
      required this.image,
      required this.price});

  @override
  GridViewOverViewState createState() => GridViewOverViewState();
}

class GridViewOverViewState extends State<GridViewOverView> {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        Get.toNamed(ProductDetailPage.routeName, arguments: widget.id);
        print(widget.id);
      },
      child: Row(
        children: <Widget>[
          Container(width: 10.0, height: 190.0, color: widget.color),
          Expanded(
            child: Padding(
              padding:
                  const EdgeInsets.symmetric(vertical: 40.0, horizontal: 20.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Text(
                    widget.title,
                    style: TextStyle(
                        color: Colors.grey.shade800,
                        fontSize: 18.0,
                        fontWeight: FontWeight.bold),
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 16.0),
                    child: Text(
                      widget.content,
                      style: TextStyle(
                          color: Colors.grey.shade500,
                          fontSize: 12.0,
                          fontWeight: FontWeight.bold),
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 8.0),
                    child: Row(
                      children: [
                        Icon(
                          Icons.star,
                          color: Colors.deepOrangeAccent,
                        ),
                        Icon(Icons.star, color: Colors.deepOrangeAccent),
                        Icon(Icons.star, color: Colors.deepOrangeAccent),
                        Icon(Icons.star_border, color: Colors.deepOrangeAccent),
                        Icon(Icons.star_border, color: Colors.deepOrangeAccent),
                      ],
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 8.0),
                    child: Text(
                      '₹ ${widget.price}',
                      style: TextStyle(
                          color: Colors.grey.shade500,
                          fontSize: 15.0,
                          fontWeight: FontWeight.bold),
                    ),
                  )
                ],
              ),
            ),
          ),
          Container(
            height: 150.0,
            width: 150.0,
            color: Colors.white,
            child: Stack(
              children: <Widget>[
                Transform.translate(
                  offset: const Offset(50.0, 0.0),
                  child: Container(
                    height: 100.0,
                    width: 100.0,
                    color: widget.color,
                  ),
                ),
                Transform.translate(
                  offset: const Offset(10.0, 20.0),
                  child: Card(
                    elevation: 40.0,
                    child: Container(
                      height: 120.0,
                      width: 120.0,
                      decoration: BoxDecoration(
                          color: Colors.white,
                          border: Border.all(
                              width: 10.0,
                              color: Colors.white,
                              style: BorderStyle.solid),
                          image: DecorationImage(
                            image: NetworkImage(widget.image),
                          )),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

product_overview.dart

The code is a Flutter app that displays a list of products in a catalog with their images, names, descriptions, prices, and colors. When a product is clicked, it navigates to a detailed page with more information about the product.

The ProductOverview class is a stateless widget that creates a ShoppingController instance using Get.put() method from the Get package. It then returns a Scaffold widget with an AppBar and a ListView.builder() widget.

The GetX widget from the Get package is used to wrap the ListView.builder() widget. The builder function of GetX widget is called whenever the state of ShoppingController changes. It builds a list of GridViewOverView widgets by mapping the products list of ShoppingController to GridViewOverView widget with the required properties.

The GridViewOverView widget is a custom widget that displays product information in a row. It also includes a GestureDetector widget that navigates to a detailed page when the product is clicked. The product information is passed to the GridViewOverView widget as properties from the ProductOverview widget.

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controller/shopping_controller.dart';
import 'widgets/grid_view.dart';

class ProductOverview extends StatelessWidget {
  final shoppingController = Get.put(ShoppingController());
  static const routeName = '/named-route';

  ProductOverview({super.key});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text('Product Catalog')),
        body: GetX<ShoppingController>(
          builder: (controller) {
            return ListView.builder(
              itemCount: controller.products.length,
              itemBuilder: (context, i) => GridViewOverView(
                content: controller.products[i].productDescription,
                image: controller.products[i].productImage,
                title: controller.products[i].productName,
                color: controller.products[i].color,
                price: controller.products[i].price,
                id: controller.products[i].id,
              ),
            );
          },
        ));
  }
}


GitHub Links

Follow @PradeepTheDeveloper Star Issue Sponsor

Comments

Popular posts from this blog

Error Handling in Flutter - Gradle issue

How to Make a Dynamic and Trending ListView with Flutter Widgets?

Understanding API integration with Getx State management