flex_widgets 0.0.1+4 copy "flex_widgets: ^0.0.1+4" to clipboard
flex_widgets: ^0.0.1+4 copied to clipboard

This is a flutter package for flex widgets.

example/lib/main.dart

import 'dart:core';
import 'package:example/dashboard.dart';
import 'package:flex_widgets/flex_widgets.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

Widget? getPageWidget(RouteSettings settings) {
  if (settings.name == null) {
    return null;
  }
  final uri = Uri.parse(settings.name!);
  switch (uri.path) {
    case '/':
      return const Dashboard();
      case '/services':
      return const ServiceBody();
    default:
      return null;
  }
}

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

  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
      designSize: const Size(360, 690),
      minTextAdapt: true,
      splitScreenMode: true,
      builder: (context, child) {
        return FlexResponsiveApp(
          builder: (context) {
            // return FlexMacosApp(
            //   title: 'Flutter Demo',
            //   debugShowCheckedModeBanner: false,
            //   theme: FlexMacosThemeData.light(),
            //   home: const HomeMacosApp(),
            // );
            return MaterialApp(
              title: 'Flutter Demo',
              theme: ThemeData(
                colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
                useMaterial3: true,
              ),
              // routes: {
              //   ScreenTwo.routeName: (context) => const ScreenTwo(tag: ''),
              //   MyHomePage.routeName: (context) => const MyHomePage(title: ''),
              // },
              // home: const MyHomePage(title: 'Flutter Demo Home Page'),
              initialRoute: '/',
              onGenerateRoute: (settings) {
                final page = getPageWidget(settings);
                if (page != null) {
                  return PageRouteBuilder(
                    settings: settings,
                    pageBuilder: (_, __, ___) => page,
                    transitionsBuilder: (_, anim, __, child) {
                      return FadeTransition(
                        opacity: anim,
                        child: child,
                      );
                    },
                  );
                }
                return null;
              },
            );
          },
        );
      },
      // child: FlexScreenTypeLayout.builder(
      //   breakpoints: FlexScreenBreakpoints(
      //     mobile: 375.0,
      //     tablet: 600.0,
      //     desktop: 1024.0,
      //     watch: 300.0,
      //   ),
      //   mobile: (context) => GestureDetector(
      //     onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
      //     child: FlexMacosApp(
      //       title: 'Flutter Demo',
      //       debugShowCheckedModeBanner: false,
      //       theme: FlexMacosThemeData.light(),
      //       home: const HomeMacosApp(
      //
      //       ),
      //     ),
      //   ),
      // ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Page Screen'),
      ),
      body: FlexMacosTheme(
        data: FlexMacosThemeData(),
        child: FlexPushButton(
          onPressed: () {},
          controlSize: ControlSize.large,
          child: const FlexText(text: 'subtitle'),
        ),
      ),
      bottomNavigationBar: NavigationBar(
        selectedIndex: 0,
        destinations: const [
          NavigationDestination(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          NavigationDestination(
            icon: Icon(Icons.search),
            label: 'Search',
          ),
          NavigationDestination(
            icon: Icon(Icons.add),
            label: 'Add',
          ),
          NavigationDestination(
            icon: Icon(Icons.settings),
            label: 'Settings',
          ),
        ],
      ),
    );
  }
}


class MyHomePage extends StatefulWidget {
  static const routeName = '/home';

  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class FlexCustomScrollView extends StatelessWidget {
  const FlexCustomScrollView({
    super.key,
    this.slivers = const <Widget>[],
    this.scrollDirection = Axis.vertical,
    this.sliverAppBar,
  });

  final List<Widget> slivers;
  final Axis scrollDirection;
  final SliverAppBar? sliverAppBar;

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      scrollDirection: scrollDirection,
      slivers: [
        sliverAppBar ?? const SliverAppBar(),
        ...slivers,
      ],
      // reverse: reverse,
      // restorationId: restorationId,
      // physics: physics,
      // scrollBehavior: scrollBehavior,
      // keyboardDismissBehavior: keyboardDismissBehavior,
      // semanticChildCount: semanticChildCount,
      // dragStartBehavior: dragStartBehavior,
    );
  }
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  int _selectedIndex = 0;

  Stream stream = Stream.value([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FlexCustomScrollView(
        sliverAppBar: SliverAppBar(
          backgroundColor: Theme.of(context).colorScheme.inversePrimary,
          title: Text(widget.title),
        ),
        slivers: [
          // SliverToBoxAdapter(
          //   child: Column(
          //     // mainAxisAlignment: MainAxisAlignment.center,
          //     children: <Widget>[
          //       Checkbox.adaptive(
          //         value: true,
          //         onChanged: (value) {},
          //       ),
          //       const CupertinoTextField(),
          //       // 5.5.height,
          //       const FlexFormField.withLable(
          //         labelName: 'Lable',
          //         hintText: '',
          //       ),
          //       // 5.5.height,
          //       FlexCheckboxListTile(
          //         title: 'Loqman',
          //         value: false,
          //         onChanged: (value) {},
          //       ),
          //       // FlexContainer(
          //       //   height: 0.1,
          //       //   color: Colors.red,
          //       //   child: FlexText.h0(
          //       //     text: 'text',
          //       //     color: Colors.white,
          //       //   ),
          //       // ),
          //       FlexDropDown(
          //         items: const [
          //           DropdownMenuItem(
          //             value: 'Loqman',
          //             child: Text('Loqman'),
          //           ),
          //           DropdownMenuItem(
          //             value: 'Yahyaa',
          //             child: Text('Yahyaa'),
          //           ),
          //         ],
          //         label: 'Loqman',
          //         onChanged: (value) {},
          //       ),
          //       const FlexExpansionTile(
          //         title: Text('Loqman'),
          //       ),
          //       FlexConditionalBuilder(
          //         condition: _counter.isEven,
          //         fallback: (context) {
          //           return const Text('Odd');
          //         },
          //         builder: (context) => const Text('Even'),
          //       ),
          //       Text(
          //         '$_counter',
          //         style: Theme.of(context).textTheme.headlineMedium,
          //       ),
          //       const FlexImageNetwork(
          //         image: 'https://picsum.photos/200/300',
          //         height: 200,
          //         width: 200,
          //       ),
          //       1.0.height,
          //       FlexOutLineButton(
          //         onPressed: () {
          //           context.showFlexToast(
          //             child: const FlexText(text: 'Loqman Toast'),
          //             bgColor: FlexColor.warning,
          //             isDismissable: true,
          //           );
          //         },
          //         text: 'FlexToast',
          //         backgroundColor: Colors.red,
          //         foregroundColor: Colors.white,
          //         borderColor: Colors.black,
          //         minimumSize: Size(context.width / 2, 0.0),
          //       ),
          //       1.0.height,
          //       FlexOutLineButtonWithIcon(
          //         onPressed: () {
          //           context.showFlexSnackBar(
          //             text: 'Flex SnackBar',
          //             color: FlexColor.warning,
          //             textColor: Colors.black,
          //             behavior: SnackBarBehavior.fixed,
          //           );
          //         },
          //         label: 'text',
          //         labelColor: Colors.white,
          //         icon: const Icon(Icons.add),
          //         backgroundColor: Colors.red,
          //         foregroundColor: Colors.white,
          //         minimumSize: Size(context.width / 2, 0.0),
          //       ),
          //       1.0.height,
          //       const FlexEmpty(),
          //       1.0.height,
          //       const FlexLoading(
          //         type: FlexLoadingType.wanderingCubes,
          //       ),
          //       15.0.height,
          //       const FlexLoadingAlertDialog(
          //         color: Colors.red,
          //         type: FlexLoadingType.circle,
          //       ),
          //       5.0.height,
          //       const FlexNoMoreData(index: 1, hasMoreData: false, limit: 1),
          //       5.0.height,
          //       FlexTreeView(
          //         nodes: [
          //           FlexTreeNode(
          //             label: '${'eg'.countryFlag} Egypt',
          //             icon: const Icon(Icons.folder),
          //             children: [
          //               FlexTreeNode(
          //                 onTap: () {
          //                   context.showFlexLoading();
          //                 },
          //                 label: 'label',
          //                 icon: const Icon(Icons.folder),
          //               ),
          //               FlexTreeNode(
          //                 onTap: () {},
          //                 label: 'label',
          //                 icon: const Icon(Icons.folder),
          //               ),
          //             ],
          //           ),
          //         ],
          //       ),
          //       5.0.height,
          //     ],
          //   ),
          // ),
          // SliverList.builder(
          //   itemCount: 50,
          //   itemBuilder: (context, index) {
          //     return ListTile(
          //       title: Hero(
          //         tag: '${index + 1}',
          //         createRectTween: (begin, end) {
          //           return MaterialRectCenterArcTween(
          //             begin: Rect.fromCircle(
          //               center: begin!.bottomRight,
          //               radius: 10,
          //             ),
          //             end: Rect.fromCircle(
          //               center: end!.bottomLeft,
          //               radius: 10,
          //             ),
          //           );
          //         },
          //         child: FlexText.h3(
          //           text: 'title ${index + 1}',
          //         ),
          //       ),
          //       trailing: FlexMacosTheme(
          //         data: FlexMacosThemeData(),
          //         child: FlexPushButton(
          //           onPressed: () {},
          //           controlSize: ControlSize.large,
          //           child: const FlexText(text: 'subtitle'),
          //         ),
          //       ),
          //       onTap: () {
          //         AppNavigator.navigatorTo(
          //           context: context,
          //           back: true,
          //           // routeName: ScreenTwo.routeName,
          //           // arguments: '${index + 1}',
          //           widget: ScreenTwo(
          //             tag: '${index + 1}',
          //           ),
          //         );
          //       },
          //     );
          //   },
          // ),
          SliverToBoxAdapter(
            child: Column(
              children: [
                // SizedBox(
                //   height: context.height / 2,
                //   child: FlexMacosTheme(
                //     data: FlexMacosThemeData(),
                //     child: FlexSidebarItems(
                //       items: const [
                //         FlexSidebarItem(
                //           label: Text('label'),
                //           leading: Icon(Icons.folder),
                //         ),
                //         FlexSidebarItem(
                //           label: Text('label'),
                //           leading: Icon(Icons.folder),
                //         ),
                //         FlexSidebarItem(
                //           label: Text('label'),
                //           leading: Icon(Icons.folder),
                //         ),
                //         FlexSidebarItem(
                //           label: Text('label'),
                //           leading: Icon(Icons.folder),
                //         ),
                //         FlexSidebarItem(
                //           label: Text('label'),
                //           leading: Icon(Icons.folder),
                //         ),
                //         FlexSidebarItem(
                //           label: Text('label'),
                //           leading: Icon(Icons.folder),
                //         ),
                //         FlexSidebarItem(
                //           label: Text('label'),
                //           leading: Icon(Icons.folder),
                //         ),
                //         FlexSidebarItem(
                //           label: Text('label'),
                //           leading: Icon(Icons.folder),
                //         ),
                //       ],
                //       currentIndex: _selectedIndex,
                //       onChanged: (index) {
                //         setState(() {
                //           _selectedIndex = index;
                //         });
                //       },
                //     ),
                //   ),
                // ),
                FlexMacosDatePicker(
                  onDateChanged: (date) {},
                ),
                FlexMacosTimePicker(
                  onTimeChanged: (time) {},
                ),
                TextButton(
                  onPressed: () {
                    FlexNavigator.navigatorTo(
                      context: context,
                      back: true,
                      widget: const Dashboard(),
                    );
                  },
                  child: const Text('Dashboard'),
                ),
                FlexMacosPopupButton(
                  popupColor: Colors.red,
                  value: 'item 1',
                  hint: const Text('hint'),
                  items: List.generate(5, (index) {
                    return FlexMacosPopupMenuItem(
                      value: 'item $index',
                      child: Text('item $index'),
                    );
                  }),
                  onChanged: (value) {
                    print(value);
                  },
                ),
                SizedBox(
                  height: context.height / 2,
                  child: FlexMacosTheme(
                    data: FlexMacosThemeData(),
                    child: ListView.builder(
                      itemCount: 50,
                      itemBuilder: (context, index) {
                        return ListTile(
                          title: Hero(
                            tag: '${index + 1}',
                            createRectTween: (begin, end) {
                              return MaterialRectCenterArcTween(
                                begin: Rect.fromCircle(
                                  center: begin!.bottomRight,
                                  radius: 10,
                                ),
                                end: Rect.fromCircle(
                                  center: end!.bottomLeft,
                                  radius: 10,
                                ),
                              );
                            },
                            child: FlexText.h3(
                              text: 'title ${index + 1}',
                            ),
                          ),
                          trailing: FlexMacosTheme(
                            data: FlexMacosThemeData(
                              primaryColor: Colors.red,
                            ),
                            child: FlexPushButton(
                              onPressed: () {},
                              controlSize: ControlSize.large,
                              color: FlexMacosColors.appleBlue,
                              child: const FlexText(text: 'subtitle'),
                            ),
                          ),
                          onTap: () {
                            // AppNavigator.navigatorTo(
                            //   context: context,
                            //   back: true,
                            //   // routeName: ScreenTwo.routeName,
                            //   // arguments: '${index + 1}',
                            //   widget: ScreenTwo(
                            //     tag: '${index + 1}',
                            //   ),
                            // );
                            FlexNavigator.navigate(
                              context: context,
                              navigatorType: FlexNavigatorType.push,
                              widget: ScreenTwo(
                                tag: '${index + 1}',
                              ),
                            );
                          },
                        );
                      },
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

class ScreenTwo extends StatelessWidget {
  static const routeName = '/2';

  const ScreenTwo({super.key, required this.tag});

  final String tag;

  @override
  Widget build(BuildContext context) {
    // final tag = ModalRoute.of(context)!.settings.arguments as String;
    return Hero(
      tag: tag,
      // flightShuttleBuilder: (flightContext, animation, flightDirection,
      //     fromHeroContext, toHeroContext) {
      //   final Hero toHero = toHeroContext.widget as Hero;
      //   return FadeTransition(
      //     opacity: animation.drive(
      //       Tween<double>(begin: 0.0, end: 1.0).chain(
      //         CurveTween(
      //           curve: const Interval(0.0, 1.0, curve: Curves.easeInOutBack),
      //         ),
      //       ),
      //     ),
      //     child: toHero.child,
      //   );
      // },
      child: Scaffold(
        body: NestedScrollView(
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return [
              const SliverAppBar(
                title: Text('Screen Two'),
              ),
              SliverToBoxAdapter(
                child: ListTile(
                  title: FlexText.h0(
                    text: 'Screen Two',
                  ),
                  onTap: () {},
                ),
              ),
            ];
          },
          body: CustomScrollView(
            slivers: [
              SliverToBoxAdapter(
                child: FlexText.h0(
                  text: tag,
                  textAlign: TextAlign.center,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class FlexDialog extends StatelessWidget {
  const FlexDialog({
    super.key,
    required this.title,
    required this.content,
    required this.actions,
  });

  final String title;
  final FlexText content;
  final List<Widget> actions;

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: Text(title),
      content: content,
      actions: actions,
    );
  }
}

class OnHoverText extends StatefulWidget {
  const OnHoverText({super.key, required this.builder});
  final Widget Function(bool isHovered) builder;

  @override
  State<OnHoverText> createState() => _OnHoverTextState();
}

class _OnHoverTextState extends State<OnHoverText> {
  bool isHover = false;

  @override
  Widget build(BuildContext context) {
    final hoveredTransform = Matrix4.identity()
      ..translate(5, 0, 0)
      ..scale(1.0);
    final transform = isHover ? hoveredTransform : Matrix4.identity();
    return MouseRegion(
      cursor: SystemMouseCursors.click,
      onEnter: (event) => onEntered(true),
      onExit: (event) => onEntered(false),
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        // curve: Sprung.overDamped,
        transform: transform,
        child: widget.builder(isHover),
      ),
    );
  }

  void onEntered(bool isHovering) {
    setState(() {
      isHover = isHovering;
    });
  }
}

class HoverToggle extends StatefulWidget {
  const HoverToggle({
    super.key,
    required this.child,
    required this.hoverChild,
    required this.size,
    this.mode = HoverMode.replace,
  });

  final Widget child;
  final Widget hoverChild;
  final HoverMode mode;
  final Size size;

  @override
  State<HoverToggle> createState() => _HoverToggleState();
}

class _HoverToggleState extends State<HoverToggle> with MaterialStateMixin {
  @override
  Widget build(BuildContext context) {
    return SizedBox.fromSize(
      size: widget.size,
      child: MouseRegion(
        cursor: isHovered ? SystemMouseCursors.click : MouseCursor.defer,
        onEnter: (_) => setMaterialState(MaterialState.hovered, true),
        onExit: (_) => setMaterialState(MaterialState.hovered, false),
        child: widget.mode == HoverMode.replace
            ? _buildReplacedChildren()
            : _buildChildrenStack(),
      ),
    );
  }

  Widget _buildChildrenStack() {
    Widget child =
        isHovered ? Opacity(opacity: 0.2, child: widget.child) : widget.child;
    return Stack(
      children: [
        child,
        if (isHovered) widget.hoverChild,
      ],
    );
  }

  Widget _buildReplacedChildren() {
    return isHovered ? widget.hoverChild : widget.child;
  }
}

enum HoverMode { replace, overlay }

class FlexListDataTable<T> extends StatefulWidget {
  const FlexListDataTable({
    super.key,
    required this.columns,
    required this.fields,
    required this.sortAscending,
    required this.onEditTap,
    required this.onDeleteTap,
    required this.listOfData,
    this.sortColumnIndex,
    this.onSort,
    this.actionWidget,
    this.actionEditWidget,
    this.actionDeleteWidget,
    this.onActionTap,
    this.isScrollable = false,
    this.headingRowHeight = 45.0,
    this.headingRowColor = Colors.redAccent,
    this.columnTextFontSize = 15.0,
    this.columnTextBold = true,
    this.columnSpacing = 30.0,
  });

  final List<String> columns;
  final List<String> fields;
  final bool sortAscending;
  final int? sortColumnIndex;
  final List<T> listOfData;
  final Function onEditTap;
  final Function onDeleteTap;
  final Function? onSort;
  final double headingRowHeight;
  final Color headingRowColor;
  final double columnTextFontSize;
  final bool columnTextBold;
  final double columnSpacing;
  final Widget? actionWidget;
  final Widget? actionEditWidget;
  final Widget? actionDeleteWidget;
  final Function? onActionTap;
  final bool isScrollable;

  @override
  State<FlexListDataTable> createState() => _FlexListDataTableState();
}

class _FlexListDataTableState extends State<FlexListDataTable> {
  List<DataRow> rows = [];
  late List<dynamic> listOfData;

  @override
  void initState() {
    super.initState();
    listOfData = widget.listOfData.map((model) {
      return rows.add(
        DataRow(
          cells: widget.fields.map((field) {
            if (field == "") {
              List<Widget> actionWidgets = [];
              if (widget.actionEditWidget == null) {
                actionWidgets.add(
                  GestureDetector(
                    child: const Icon(
                      Icons.edit,
                      color: Colors.black,
                    ),
                    onTap: () {
                      widget.onEditTap(model);
                    },
                  ),
                );
              } else {
                actionWidgets.add(
                  GestureDetector(
                    child: widget.actionEditWidget,
                    onTap: () {
                      widget.onEditTap(model);
                    },
                  ),
                );
              }

              if (widget.actionDeleteWidget == null) {
                actionWidgets.add(
                  GestureDetector(
                    child: const Icon(
                      Icons.delete,
                      color: Colors.red,
                    ),
                    onTap: () {
                      widget.onDeleteTap(model);
                    },
                  ),
                );
              } else {
                actionWidgets.add(
                  GestureDetector(
                    child: widget.actionDeleteWidget,
                    onTap: () {
                      widget.onDeleteTap(model);
                    },
                  ),
                );
              }

              if (widget.actionWidget != null) {
                actionWidgets.add(
                  GestureDetector(
                    child: widget.actionWidget,
                    onTap: () {
                      widget.onActionTap!(model);
                    },
                  ),
                );
              }
              return DataCell(
                Align(
                  alignment: Alignment.centerRight,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    crossAxisAlignment: CrossAxisAlignment.end,
                    children: actionWidgets,
                  ),
                ),
              );
            } else {
              return DataCell(FlexText(
                text: _getValue(model, field).toString(),
              ));
            }
          }).toList(),
        ),
      );
    }).toList();
  }

  dynamic _getValue(Map<String, dynamic> mapRep, String propertyName) {
    if (mapRep.containsKey(propertyName)) {
      return mapRep[propertyName] ?? "";
    }
    throw ArgumentError('Property not found : $propertyName');
  }

  @override
  Widget build(BuildContext context) {
    return FlexDataTable(
      columns: widget.columns,
      fields: widget.fields,
      sortAscending: widget.sortAscending,
      listOfData: listOfData,
      onEditTap: widget.onEditTap,
      onDeleteTap: widget.onDeleteTap,
      rows: rows,
      onSort: widget.onSort,
      headingRowHeight: widget.headingRowHeight,
      headingRowColor: widget.headingRowColor,
      columnTextFontSize: widget.columnTextFontSize,
      columnTextBold: widget.columnTextBold,
      columnSpacing: widget.columnSpacing,
      isScrollable: widget.isScrollable,
    );
  }
}

class FlexDataTable extends StatefulWidget {
  const FlexDataTable({
    super.key,
    required this.columns,
    required this.fields,
    required this.sortAscending,
    required this.onEditTap,
    required this.onDeleteTap,
    required this.rows,
    required this.listOfData,
    this.sortColumnIndex,
    this.onSort,
    this.headingRowHeight = 45.0,
    this.headingRowColor = Colors.redAccent,
    this.columnTextFontSize = 15.0,
    this.columnTextBold = true,
    this.columnSpacing = 30.0,
    this.isScrollable = false,
  });

  final List<String> columns;
  final List<String> fields;
  final bool sortAscending;
  final int? sortColumnIndex;
  final List listOfData;
  final Function onEditTap;
  final Function onDeleteTap;
  final List<DataRow> rows;
  final Function? onSort;
  final double headingRowHeight;
  final Color headingRowColor;
  final double columnTextFontSize;
  final bool columnTextBold;
  final double columnSpacing;
  final bool isScrollable;

  @override
  State<FlexDataTable> createState() => _FlexDataTableState();
}

class _FlexDataTableState extends State<FlexDataTable> {
  late Widget table;

  @override
  void initState() {
    super.initState();
    table = DataTable(
      headingRowColor: MaterialStateColor.resolveWith(
        (states) => widget.headingRowColor,
      ),
      headingRowHeight: widget.headingRowHeight,
      sortAscending: widget.sortAscending,
      sortColumnIndex: widget.sortColumnIndex,
      columns: widget.columns.map(
        (columnName) {
          return DataColumn(
            label: FlexText(
              text: columnName,
              fontSize: widget.columnTextFontSize,
              fontWeight: widget.columnTextBold ? FontWeight.w900 : null,
            ),
            onSort: (columnIndex, ascending) {
              widget.onSort!(
                  columnIndex, widget.fields[columnIndex], ascending);
            },
          );
        },
      ).toList(),
      columnSpacing: widget.columnSpacing,
      rows: widget.rows,
    );
  }

  @override
  Widget build(BuildContext context) {
    return widget.isScrollable
        ? SingleChildScrollView(
            scrollDirection: Axis.vertical,
            child: SingleChildScrollView(
              scrollDirection: Axis.horizontal,
              child: table,
            ),
          )
        : SizedBox(width: context.width, child: table);
  }
}

class ListUtils {
  ListUtils._internal();

  static final ListUtils instance = ListUtils._internal();

  Widget buildDataTable<T>({
    required BuildContext context,
    required List<String> columns,
    required List<String> fields,
    required bool sortAscending,
    required int? sortColumnIndex,
    required dynamic listOfData,
    required Function onEditTap,
    required Function onDeleteTap,
    required Function onSort,
    double headingRowHeight = 45,
    Color headingRowColor = Colors.redAccent,
    double columnTextFontSize = 15,
    bool columnTextBold = true,
    double columnSpacing = 30,
    Widget? actionWidget,
    Widget? actionEditWidget,
    Widget? actionDeleteWidget,
    Function? onActionTap,
    bool isScrollable = false,
    // bool refreshIndicator = false,
    // Key refreshkey,
    // Function onRefresh,
  }) {
    List<DataRow> rows = [];
    listOfData.forEach(
      (model) {
        rows.add(
          DataRow(
            cells: fields.map(
              (field) {
                if (field == "") {
                  List<Widget> actionWidgets = [];

                  if (actionEditWidget == null) {
                    actionWidgets.add(
                      GestureDetector(
                        child: const Icon(
                          Icons.edit,
                          color: Colors.black,
                        ),
                        onTap: () {
                          onEditTap(model);
                        },
                      ),
                    );
                  } else {
                    actionWidgets.add(
                      GestureDetector(
                        child: actionEditWidget,
                        onTap: () {
                          onEditTap(model);
                        },
                      ),
                    );
                  }

                  if (actionDeleteWidget == null) {
                    actionWidgets.add(
                      GestureDetector(
                        child: const Icon(
                          Icons.delete,
                          color: Colors.red,
                        ),
                        onTap: () {
                          onDeleteTap(model);
                        },
                      ),
                    );
                  } else {
                    actionWidgets.add(
                      GestureDetector(
                        child: actionDeleteWidget,
                        onTap: () {
                          onDeleteTap(model);
                        },
                      ),
                    );
                  }

                  if (actionWidget != null) {
                    actionWidgets.add(
                      GestureDetector(
                        child: actionWidget,
                        onTap: () {
                          onActionTap!(model);
                        },
                      ),
                    );
                  }

                  return DataCell(
                    Align(
                      alignment: Alignment.centerRight,
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceAround,
                        crossAxisAlignment: CrossAxisAlignment.end,
                        children: actionWidgets,
                      ),
                    ),
                  );
                } else {
                  return DataCell(
                    Text(
                      _getValue(model, field).toString(),
                    ),
                  );
                }
              },
            ).toList(),
          ),
        );
      },
    );

    // return refreshIndicator
    //     ? Container(
    //         child: RefreshIndicator(
    //           key: refreshkey,
    //           onRefresh: () {
    //             return onRefresh();
    //           },
    //           child: _dataTable<T>(
    //             context,
    //             columns,
    //             fields,
    //             sortAscending,
    //             sortColumnIndex,
    //             listOfData,
    //             onEditTap,
    //             onDeleteTap,
    //             rows,
    //             onSort: onSort,
    //             headingRowHeight: headingRowHeight,
    //             headingRowColor: headingRowColor,
    //             columnTextFontSize: columnTextFontSize,
    //             columnTextBold: columnTextBold,
    //             columnSpacing: columnSpacing,
    //           ),
    //         ),
    //       )
    return _dataTable<T>(
      context,
      columns,
      fields,
      sortAscending,
      sortColumnIndex,
      listOfData,
      onEditTap,
      onDeleteTap,
      rows,
      onSort: onSort,
      headingRowHeight: headingRowHeight,
      headingRowColor: headingRowColor,
      columnTextFontSize: columnTextFontSize,
      columnTextBold: columnTextBold,
      columnSpacing: columnSpacing,
      isScrollable: isScrollable,
    );
  }

  Widget _dataTable<T>(
    BuildContext context,
    List<String> columns,
    List<String> fields,
    bool sortAscending,
    int? sortColumnIndex,
    dynamic listOfData,
    Function onEditTap,
    Function onDeleteTap,
    List<DataRow> rows, {
    Function? onSort,
    double headingRowHeight = 45,
    Color headingRowColor = Colors.redAccent,
    double columnTextFontSize = 15,
    bool columnTextBold = true,
    double columnSpacing = 30,
    bool isScrollable = false,
  }) {
    Widget table = DataTable(
      headingRowColor: MaterialStateColor.resolveWith(
        (states) => headingRowColor,
      ),
      headingRowHeight: headingRowHeight,
      sortAscending: sortAscending,
      sortColumnIndex: sortColumnIndex,
      columns: columns.map(
        (columnName) {
          return DataColumn(
            label: Text(
              columnName,
              style: TextStyle(
                fontSize: columnTextFontSize,
                fontWeight: columnTextBold ? FontWeight.w900 : null,
              ),
            ),
            onSort: (columnIndex, ascending) {
              onSort!(columnIndex, fields[columnIndex], ascending);
            },
          );
        },
      ).toList(),
      columnSpacing: columnSpacing,
      rows: rows,
    );

    return isScrollable
        ? SingleChildScrollView(
            scrollDirection: Axis.vertical,
            child: SingleChildScrollView(
              scrollDirection: Axis.horizontal,
              child: table,
            ),
          )
        : SizedBox(width: MediaQuery.of(context).size.width, child: table);
  }

  static dynamic _getValue(Map<String, dynamic> mapRep, String propertyName) {
    if (mapRep.containsKey(propertyName)) {
      return mapRep[propertyName] ?? "";
    }
    throw ArgumentError('Property not found : $propertyName');
  }
}
2
likes
80
points
3
downloads

Publisher

unverified uploader

Weekly Downloads

This is a flutter package for flex widgets.

Homepage

Documentation

API reference

License

MIT (license)

Dependencies

cached_network_image, equatable, flutter, flutter_screenutil, flutter_spinkit, flutter_svg, intl

More

Packages that depend on flex_widgets