build method

  1. @override
Widget build(
  1. BuildContext context
)
override

Builds the complete table UI with pinned headers, scrollable rows, and Forui styling.

Layout structure:

  1. Container with Forui FCard styling (borders, rounded corners, background)
  2. Column with:
    • Pinned header row: Row with all header cells, vertically padded
    • Divider: Subtle Forui FDivider separating header from rows
    • Scrollable ListView: Rows with item separators (dividers) between each row

Each cell is wrapped in:

  • Expanded with flex ratio from columnFlex
  • Padding based on density
  • Align based on _getAlignment result
  • Normalized widget from _normalizeCell

See class documentation for example usage.

Implementation

@override
Widget build(BuildContext context) {
  // We fetch the theme configuration to replicate Forui's FCard styling exactly
  final theme = FTheme.of(context);

  return Container(
    constraints: BoxConstraints(maxHeight: height),
    // Replicating Forui's FCard aesthetic: clean borders, rounded corners, and background
    decoration: theme.cardStyle.decoration,
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisSize: MainAxisSize.min,
      children: [
        // 1. Pinned Header Row
        Padding(
          padding: EdgeInsets.symmetric(
            vertical: density.verticalPadding,
            horizontal: density.horizontalPadding,
          ),
          child: Row(
            children: List.generate(headers.length, (index) {
              return Expanded(
                flex: columnFlex[index],
                child: Padding(
                  padding: EdgeInsets.symmetric(
                    horizontal: density.columnSpacing,
                  ),
                  child: Align(
                    alignment: _getAlignment(index),
                    child: _normalizeCell(headers[index], isHeader: true),
                  ),
                ),
              );
            }),
          ),
        ),

        // Forui native subtle divider line
        const FDivider(style: .delta(padding: .value(EdgeInsets.zero))),

        // 2. Bound Scrollable Rows Viewport
        Flexible(
          child: ListView.separated(
            shrinkWrap: true,
            padding: EdgeInsets.symmetric(vertical: density.verticalPadding),
            itemCount: rows.length,
            separatorBuilder: (context, index) => FDivider(
              style: .delta(
                padding: .value(
                  EdgeInsets.symmetric(vertical: density.verticalPadding),
                ),
              ),
            ),
            itemBuilder: (context, rowIndex) {
              final rowData = rows[rowIndex];
              return Padding(
                padding: EdgeInsets.symmetric(
                  horizontal: density.horizontalPadding,
                ),
                child: Row(
                  children: List.generate(rowData.length, (colIndex) {
                    return Expanded(
                      flex: columnFlex[colIndex],
                      // Added identical padding to cell body blocks
                      child: Padding(
                        padding: EdgeInsets.symmetric(
                          horizontal: density.columnSpacing,
                        ),
                        child: Align(
                          alignment: _getAlignment(colIndex),
                          child: _normalizeCell(rowData[colIndex]),
                        ),
                      ),
                    );
                  }),
                ),
              );
            },
          ),
        ),
      ],
    ),
  );
}