Search code examples
flutteruser-interfaceflutter-layoutflutter-web

Flutter. How to create tree graph structure inside a column


I need to create UI for a query builder. I want to do something like this enter image description here

The problem is that I have no idea how to create the And/Or operator "brackets".


  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Row(
          children: [
            Operator(),
            Column(
              children: childFiltersAndGroups,
            ),
          ],
        ),
        Actions(...),
      ],
    );
  }

Could someone guide me on how to implement the Operator widget please? I don't need help with the rest of the stuff.


Solution

  • Maybe this will help:

    class Operator extends StatelessWidget {
      final String operatorValue;
      final Color color;
      final Color? textBackgroundColor;
    
      const Operator({Key? key, required this.operatorValue, required this.color, this.textBackgroundColor})
          : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Stack(
          alignment: Alignment.center,
          children: [
            CustomPaint(
              painter: BracketPainter(color),
              size: const Size(double.infinity, double.infinity)
            ),
            Container(
              padding: EdgeInsets.all(4),
              decoration: BoxDecoration(
                borderRadius: const BorderRadius.all(
                  Radius.circular(20),
                ),
                color: textBackgroundColor ?? color,
              ),
              child: Text(operatorValue),
            )
          ],
        );
      }
    }
    
    
    class BracketPainter extends CustomPainter {
      final Color color;
    
      BracketPainter(this.color);
    
      @override
      void paint(Canvas canvas, Size size) {
        final centerX = size.width / 2;
        final path = Path()
          ..moveTo(size.width, 0)
          ..lineTo(centerX, 0)
          ..lineTo(centerX, size.height)
          ..lineTo(size.width, size.height);
        final paint = Paint()
          ..color = color
          ..style = PaintingStyle.stroke
          ..strokeWidth = 2;
        canvas.drawPath(path, paint);
      }
    
      @override
      bool shouldRepaint(covariant CustomPainter oldDelegate) {
        return this != oldDelegate;
      }
    }
    

    example usage:

    return SizedBox(
      height: 200,
      width: 40,
      child: Operator(
        operatorValue: "AND",
        color: Colors.green,
        textBackgroundColor: Colors.green[300],
      ),
    );
    

    In DartPad this rendered like this:

    enter image description here