skip to Main Content

I have a Widget tree like:

  • App Body
    • Column of Widgets
      • A Widget with a Table
        • Each TableRow has a TableCell
          • And in a TableCell there is a Widget that spans over multiple Rows and Columns of the table (like a number circled with a huge circle, also multiple numbers can have these circles).

The table has variable alignment based on the data in the table. All the circles need to be on top of all the cells. And each circle has a shadow. Ideally a circle would not cast a shadow on another circle.

The issue is, with placing the "circle" in a TableCell, it is covered by the next cell/row. In html I would use z-index which looks like it is not present in Flutter. Is there another option how to do that, other than constructing another stacked layer of invisible table just to get the position of the circles right?

The final result should look something like this:

enter image description here

Thank you!

2

Answers


  1. Chosen as BEST ANSWER

    I ended up creating a concept of layers. Basically rendering the same table on 2 layers. The base layer is the table without circles, the second layer is the same table with the circles and the cells rendered as transparent. This way, the "circle" layer positions the circles correctly but everything that could cover the circles is transparent.


  2. I recommend that you create a Custom Table Cell which would have a boolean to add or not a circle to the cell and I will add this CustomTableCell to the TableRow() of the Table like these:

    class TableWithOverlays extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Table(
          border: TableBorder.all(),
          columnWidths: {
            0: FlexColumnWidth(1),
            1: FlexColumnWidth(1),
            2: FlexColumnWidth(1),
            3: FlexColumnWidth(3),
          },
          children: [
            TableRow(children: [
              CustomTableCell(child: Text('TABLE CELL')),
              CustomTableCell(child: Text('1')),
              CustomTableCell(child: Text('1234'), hasCircle: true),
              CustomTableCell(child: Text('SOME RANDOM LONG TEEEEEEEEEEEEEEEEEXT')),
            ]),
            TableRow(children: [
              CustomTableCell(child: Text('TABLE CELL')),
              CustomTableCell(child: Text('1'), hasCircle: true),
              CustomTableCell(child: Text('1234')),
              CustomTableCell(child: Text('')),
            ]),
            TableRow(children: [
              CustomTableCell(child: Text('TABLE CELL')),
              CustomTableCell(child: Text('1')),
              CustomTableCell(child: Text('1234')),
              CustomTableCell(child: Text('')),
            ]),
            TableRow(children: [
              CustomTableCell(child: Text('TABLE CEEEEEELL')),
              CustomTableCell(child: Text('1')),
              CustomTableCell(child: Text('50'), hasCircle: true),
              CustomTableCell(child: Text('')),
            ]),
            TableRow(children: [
              CustomTableCell(child: Text('TABLE CELL')),
              CustomTableCell(child: Text('1')),
              CustomTableCell(child: Text('1234')),
              CustomTableCell(child: Text('')),
            ]),
          ],
        );
      }
    }
    
    class CustomTableCell extends StatelessWidget {
      final Widget child;
      final bool hasCircle;
    
      CustomTableCell({required this.child, this.hasCircle = false});
    
      @override
      Widget build(BuildContext context) {
        return Stack(
          alignment: Alignment.center,
          children: [
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: child,
            ),
            if (hasCircle)
              Positioned.fill(
                child: Align(
                  alignment: Alignment.center,
                  child: CircleWidget(),
                ),
              ),
          ],
        );
      }
    }
    
    class CircleWidget extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Container(
          width: 40,
          height: 40,
          decoration: BoxDecoration(
            shape: BoxShape.circle,
            border: Border.all(
              color: Colors.red,
              width: 2.0,
            ),
            boxShadow: [
              BoxShadow(
                color: Colors.black.withOpacity(0.2),
                blurRadius: 5,
                spreadRadius: 2,
              ),
            ],
          ),
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search