view_matrix 1.2.0 copy "view_matrix: ^1.2.0" to clipboard
view_matrix: ^1.2.0 copied to clipboard

A flexible and extensible Flutter framework for rendering list and grid views with unified API and local data handling.

example/lib/main.dart

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

void main() => runApp(const ExampleApp());

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: "ViewMatrix Example",
      theme: ThemeData(
        colorSchemeSeed: Colors.indigo,
        useMaterial3: true,
      ),
      home: const ExampleHome(),
    );
  }
}

class ExampleHome extends StatelessWidget {
  const ExampleHome({super.key});

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 7,
      child: Scaffold(
        backgroundColor: Colors.grey.shade100,
        appBar: AppBar(
          elevation: 1,
          shadowColor: Colors.transparent,
          surfaceTintColor: Colors.transparent,
          backgroundColor: Colors.white,
          title: const Text(
            "ViewMatrix Examples",
            style: TextStyle(
              fontWeight: FontWeight.w700,
              fontSize: 21,
              color: Colors.indigo,
            ),
          ),
          bottom: PreferredSize(
            preferredSize: const Size.fromHeight(48),
            child: Align(
              alignment: Alignment.centerLeft,
              child: TabBar(
                isScrollable: true,

                // -------- TEXT --------
                labelColor: Colors.indigo,
                unselectedLabelColor: Colors.black54,
                labelStyle: const TextStyle(
                  fontSize: 15,
                  fontWeight: FontWeight.w700,
                ),
                unselectedLabelStyle: const TextStyle(
                  fontSize: 15,
                  fontWeight: FontWeight.w500,
                ),

                // -------- SPACING --------
                labelPadding:
                    const EdgeInsets.symmetric(horizontal: 16, vertical: 10),

                // -------- PROPER UNDERLINE INDICATOR --------
                indicator: const UnderlineTabIndicator(
                  borderSide: BorderSide(
                    color: Colors.indigo,
                    width: 3,
                  ),
                  insets: EdgeInsets.symmetric(horizontal: 16),
                ),
                indicatorSize: TabBarIndicatorSize.label,

                tabs: const [
                  Tab(text: "API - GET"),
                  Tab(text: "API - POST"),
                  Tab(text: "Local Grid"),
                  Tab(text: "Fully Custom UI"),
                  Tab(text: "Custom Builder List"),
                  Tab(text: "Custom Builder Grid"),
                  Tab(text: "Minimal Grid"),
                ],
              ),
            ),
          ),
        ),
        body: const TabBarView(
          children: [
            ApiGetExample(),
            ApiPostExample(),
            LocalGridExample(),
            FullCustomExample(),
            CustomItemBuilderExample(),
            CustomItemBuilderGridExample(),
            CustomItemBuilderGridMinimalExample(),
          ],
        ),
      ),
    );
  }
}

//
// -------------------------------------------------------------
// 1️⃣ API GET EXAMPLE
// -------------------------------------------------------------
class ApiGetExample extends StatelessWidget {
  const ApiGetExample({super.key});

  @override
  Widget build(BuildContext context) {
    return ViewMatrix(
      viewType: ViewType.list,
      sourceType: SourceType.api,
      apiConfig: ApiConfig(
        url: "https://fakestoreapi.com/products",
        method: HttpMethod.get,
        enableLogging: true,
        showOnly: [
          DataItem.fieldImage,
          DataItem.fieldTitle,
          DataItem.fieldDescription,
          DataItem.fieldBadge,
        ],
        fieldMapping: {
          DataItem.fieldTitle: "title",
          DataItem.fieldDescription: "description",
          DataItem.fieldImage: "image",
          DataItem.fieldBadge: "category"
        },
      ),
      uiConfig: ViewMatrixUIConfig(
        titleStyle: const TextStyle(
          fontSize: 17,
          fontWeight: FontWeight.bold,
          color: Colors.indigo,
        ),
        descriptionStyle: TextStyle(
          fontSize: 13,
          color: Colors.grey.shade700,
        ),
        badgeStyle: const TextStyle(
          color: Colors.indigo,
          fontSize: 12,
          fontWeight: FontWeight.w600,
        ),
        badgeBackgroundColor: Colors.indigo.shade50,
        cardRadius: 16,
        cardElevation: 2,
        imageHeight: 150,
        loaderColor: Colors.indigo,
      ),
    );
  }
}

//
// -------------------------------------------------------------
// 2️⃣ API POST
// -------------------------------------------------------------
class ApiPostExample extends StatelessWidget {
  const ApiPostExample({super.key});

  @override
  Widget build(BuildContext context) {
    return ViewMatrix(
      viewType: ViewType.list,
      sourceType: SourceType.api,
      apiConfig: ApiConfig(
        url: "https://jsonplaceholder.typicode.com/posts",
        method: HttpMethod.post,
        enableLogging: true,
        body: {
          "title": "ViewMatrix User",
          "body": "Flutter Developer",
          "userId": 1
        },
        successStatusCodes: [200, 201, 202, 204],
        showOnly: [
          DataItem.fieldTitle,
          DataItem.fieldDescription,
          DataItem.fieldBadge
        ],
        fieldMapping: {
          DataItem.fieldTitle: "title",
          DataItem.fieldDescription: "body",
          DataItem.fieldBadge: "userId"
        },
      ),
      uiConfig: ViewMatrixUIConfig(
        titleStyle: const TextStyle(
          fontSize: 17,
          fontWeight: FontWeight.bold,
          color: Colors.green,
        ),
        badgeBackgroundColor: Colors.green.shade50,
        badgeStyle: const TextStyle(
          color: Colors.green,
          fontWeight: FontWeight.w500,
        ),
        loaderColor: Colors.green,
        cardRadius: 16,
      ),
    );
  }
}

//
// -------------------------------------------------------------
// 3️⃣ Local Grid
// -------------------------------------------------------------
class LocalGridExample extends StatelessWidget {
  const LocalGridExample({super.key});

  @override
  Widget build(BuildContext context) {
    return ViewMatrix(
      viewType: ViewType.grid,
      sourceType: SourceType.nonApi,
      localItems: [
        DataItem(title: "Laptop", description: "Macbook Pro", badge: "Tech"),
        DataItem(title: "Bike", description: "Yamaha R15", badge: "Vehicles"),
        DataItem(title: "Shoes", description: "Nike Air", badge: "Fashion"),
        DataItem(title: "Phone", description: "iPhone 15 Pro", badge: "Tech"),
        DataItem(title: "Watch", description: "Apple Watch", badge: "Tech"),
        DataItem(title: "Camera", description: "Sony A7", badge: "Tech"),
      ],
      uiConfig: ViewMatrixUIConfig(
        gridCrossAxisCount: 3,
        gridSpacing: 16,
        cardRadius: 18,
        imageHeight: 110,
        badgeBackgroundColor: Colors.orange.shade50,
        badgeStyle: const TextStyle(
          color: Colors.deepOrange,
          fontWeight: FontWeight.bold,
        ),
      ),
    );
  }
}

//
// -------------------------------------------------------------
// 4️⃣ Custom Dark Grid
// -------------------------------------------------------------
class FullCustomExample extends StatelessWidget {
  const FullCustomExample({super.key});

  @override
  Widget build(BuildContext context) {
    return ViewMatrix(
      viewType: ViewType.grid,
      sourceType: SourceType.api,
      apiConfig: ApiConfig(
        url: "https://fakestoreapi.com/products",
        method: HttpMethod.get,
        enableLogging: false,
        fieldMapping: {
          DataItem.fieldTitle: "title",
          DataItem.fieldDescription: "description",
          DataItem.fieldImage: "image",
        },
      ),
      uiConfig: ViewMatrixUIConfig(
        gridCrossAxisCount: 2,
        customGridBuilder: (item) {
          return Container(
            margin: const EdgeInsets.all(10),
            decoration: BoxDecoration(
              color: Colors.black87,
              borderRadius: BorderRadius.circular(18),
            ),
            child: Column(
              children: [
                Expanded(
                  child: ClipRRect(
                    borderRadius:
                        const BorderRadius.vertical(top: Radius.circular(18)),
                    child: Image.network(
                      item.image ?? "",
                      fit: BoxFit.cover,
                      width: double.infinity,
                    ),
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(12),
                  child: Text(
                    item.title,
                    style: const TextStyle(
                        color: Colors.white,
                        fontSize: 15,
                        fontWeight: FontWeight.bold),
                    maxLines: 2,
                    overflow: TextOverflow.ellipsis,
                  ),
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}

//
// -------------------------------------------------------------
// 5️⃣ List Gradient
// -------------------------------------------------------------
class CustomItemBuilderExample extends StatelessWidget {
  const CustomItemBuilderExample({super.key});

  @override
  Widget build(BuildContext context) {
    return ViewMatrix(
      viewType: ViewType.list,
      sourceType: SourceType.api,
      apiConfig: ApiConfig(
        url: "https://fakestoreapi.com/products",
        method: HttpMethod.get,
        fieldMapping: {
          DataItem.fieldTitle: "title",
          DataItem.fieldDescription: "description",
          DataItem.fieldImage: "image",
          DataItem.fieldBadge: "category",
        },
      ),
      itemBuilder: (context, item, index) {
        return Card(
          elevation: 5,
          margin: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
          shape:
              RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
          child: Container(
            decoration: BoxDecoration(
              gradient: LinearGradient(
                colors: [Colors.purple.shade400, Colors.blue.shade400],
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
              ),
              borderRadius: BorderRadius.circular(20),
            ),
            padding: const EdgeInsets.all(16),
            child: Row(
              children: [
                ClipRRect(
                  borderRadius: BorderRadius.circular(14),
                  child: Image.network(
                    item.image ?? "",
                    width: 80,
                    height: 80,
                    fit: BoxFit.cover,
                  ),
                ),
                const SizedBox(width: 14),
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        item.title,
                        style: const TextStyle(
                          color: Colors.white,
                          fontSize: 18,
                          fontWeight: FontWeight.bold,
                        ),
                        maxLines: 2,
                        overflow: TextOverflow.ellipsis,
                      ),
                      const SizedBox(height: 4),
                      if (item.description != null)
                        Text(
                          item.description!,
                          style: const TextStyle(
                              color: Colors.white70, fontSize: 13),
                          maxLines: 2,
                          overflow: TextOverflow.ellipsis,
                        ),
                      const SizedBox(height: 8),
                      if (item.badge != null)
                        Container(
                          padding: const EdgeInsets.symmetric(
                              horizontal: 10, vertical: 5),
                          decoration: BoxDecoration(
                            color: Colors.white24,
                            borderRadius: BorderRadius.circular(12),
                          ),
                          child: Text(
                            item.badge!,
                            style: const TextStyle(
                                color: Colors.white,
                                fontWeight: FontWeight.w600),
                          ),
                        ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        );
      },
    );
  }
}

//
// -------------------------------------------------------------
// 6️⃣ Grid Gradient
// -------------------------------------------------------------
class CustomItemBuilderGridExample extends StatelessWidget {
  const CustomItemBuilderGridExample({super.key});

  @override
  Widget build(BuildContext context) {
    return ViewMatrix(
      viewType: ViewType.grid,
      sourceType: SourceType.api,
      apiConfig: ApiConfig(
        url: "https://fakestoreapi.com/products",
        method: HttpMethod.get,
        fieldMapping: {
          DataItem.fieldTitle: "title",
          DataItem.fieldDescription: "description",
          DataItem.fieldImage: "image",
          DataItem.fieldBadge: "category",
        },
      ),
      itemBuilder: (context, item, index) {
        return Container(
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(20),
            gradient: LinearGradient(
              colors: [Colors.indigo.shade400, Colors.deepPurple.shade600],
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
            ),
          ),
          child: ClipRRect(
            borderRadius: BorderRadius.circular(20),
            child: Column(
              children: [
                Expanded(
                  flex: 6,
                  child: Image.network(
                    item.image ?? "",
                    width: double.infinity,
                    fit: BoxFit.cover,
                  ),
                ),
                Expanded(
                  flex: 4,
                  child: Padding(
                    padding: const EdgeInsets.all(12),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        if (item.badge != null)
                          Container(
                            padding: const EdgeInsets.symmetric(
                                horizontal: 8, vertical: 4),
                            decoration: BoxDecoration(
                              color: Colors.white24,
                              borderRadius: BorderRadius.circular(8),
                            ),
                            child: Text(
                              item.badge!,
                              style: const TextStyle(
                                  color: Colors.white, fontSize: 11),
                            ),
                          ),
                        const SizedBox(height: 6),
                        Expanded(
                          child: Text(
                            item.title,
                            style: const TextStyle(
                              color: Colors.white,
                              fontWeight: FontWeight.bold,
                              fontSize: 14,
                            ),
                            maxLines: 2,
                            overflow: TextOverflow.ellipsis,
                          ),
                        ),
                        if (item.description != null)
                          Text(
                            item.description!,
                            style: const TextStyle(
                                color: Colors.white70, fontSize: 10),
                            maxLines: 1,
                            overflow: TextOverflow.ellipsis,
                          ),
                      ],
                    ),
                  ),
                )
              ],
            ),
          ),
        );
      },
      uiConfig: ViewMatrixUIConfig(
        gridCrossAxisCount: 2,
        gridSpacing: 14,
        gridChildAspectRatio: 0.76,
      ),
    );
  }
}

//
// -------------------------------------------------------------
// 7️⃣ Minimal Grid
// -------------------------------------------------------------
class CustomItemBuilderGridMinimalExample extends StatelessWidget {
  const CustomItemBuilderGridMinimalExample({super.key});

  @override
  Widget build(BuildContext context) {
    return ViewMatrix(
      viewType: ViewType.grid,
      sourceType: SourceType.api,
      apiConfig: ApiConfig(
        url: "https://fakestoreapi.com/products",
        method: HttpMethod.get,
        fieldMapping: {
          DataItem.fieldTitle: "title",
          DataItem.fieldImage: "image",
          DataItem.fieldBadge: "category",
        },
      ),
      itemBuilder: (context, item, index) {
        return Container(
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(16),
            boxShadow: [
              BoxShadow(
                color: Colors.black.withAlpha(20),
                blurRadius: 10,
              )
            ],
          ),
          child: ClipRRect(
            borderRadius: BorderRadius.circular(16),
            child: Column(
              children: [
                Expanded(
                  flex: 7,
                  child: Stack(
                    children: [
                      Positioned.fill(
                        child: Image.network(
                          item.image ?? "",
                          fit: BoxFit.cover,
                        ),
                      ),
                      if (item.badge != null)
                        Positioned(
                          top: 8,
                          right: 8,
                          child: Container(
                            padding: const EdgeInsets.symmetric(
                                horizontal: 10, vertical: 5),
                            decoration: BoxDecoration(
                              color: Colors.white,
                              borderRadius: BorderRadius.circular(20),
                            ),
                            child: Text(
                              item.badge!,
                              style: const TextStyle(
                                  fontSize: 10, fontWeight: FontWeight.bold),
                            ),
                          ),
                        ),
                    ],
                  ),
                ),
                Expanded(
                  flex: 3,
                  child: Padding(
                    padding: const EdgeInsets.all(10),
                    child: Text(
                      item.title,
                      maxLines: 3,
                      overflow: TextOverflow.ellipsis,
                      style: const TextStyle(
                        fontSize: 14,
                        fontWeight: FontWeight.w600,
                        color: Colors.black87,
                      ),
                    ),
                  ),
                )
              ],
            ),
          ),
        );
      },
      uiConfig: ViewMatrixUIConfig(
        gridCrossAxisCount: 2,
        gridSpacing: 18,
        gridChildAspectRatio: 0.8,
      ),
    );
  }
}
3
likes
160
points
6
downloads

Publisher

verified publisherronak-vasoliya.devservers.site

Weekly Downloads

A flexible and extensible Flutter framework for rendering list and grid views with unified API and local data handling.

Homepage

Documentation

API reference

License

MIT (license)

Dependencies

flutter, http, intl

More

Packages that depend on view_matrix