flutter – Handel SingleChildScrollView in MultiChildRenderObjectWidget

I’m just getting started with custom UI using RenderBox. When I learn about MultiChildRenderObjectWidget and do a little example of it, I came across the following problem:
When I insert a list of many children on the screen, the height of the widgets will be larger than the height of the screen. Now I add a SingleChildScrollView tag to allow scrolling up to view. And the error happened.It cannot scroll. And throw error like bellow. I tried to change the size property in the performLayout() method. But get the desired result.

Unimplemented handling of missing static target

When the exception was thrown, this was the stack: #0 RenderObject._updateCompositingBits (package:flutter/src/rendering/object.dart:2158:5) #1 RenderObject._updateCompositingBits. (package:flutter/src/rendering/object.dart:2159:13) #2 RenderObjectWithChildMixin.visitChildren (package:flutter/src/rendering/object.dart:3122:14) #3 RenderObject._updateCompositingBits (package:flutter/src /rendering/object.dart:2158:5) #4 RenderObject._updateCompositingBits. (package:flutter/src/rendering/object.dart:2159:13) #5 ContainerRenderObjectMixin.visitChildren (package:flutter/src/rendering/object.dart:3406:14) #6 RenderObject._updateCompositingBits (package:flutter/src) /rendering/object.dart:2158:5) #7 RenderObject._updateCompositingBits. (package:flutter/src/rendering/object.dart:2159:13) #8 RenderObjectWithChildMixin.visitChildren (package:flutter/src/rendering/object.dart:3122:14) #9 RenderObject._updateCompositingBits (package:flutter/src /rendering/object.dart:2158:5) #10 RenderObject._updateCompositingBits. (package:flutter/src/rendering/object.dart:2159:13)

…. Hope anyone can help with the concept and solution to my problem.

Here is a picture of the example and the full code of the example

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: SingleChildScrollView(
        child: BranchComponent(
          children: [
            Container(
                height: 100,
                color: Colors.red,
                child: const Text('1')),
            Container(
                height: 20,
                width: double.infinity,
                color: Colors.blue,
                child: const Text('2')),
            Container(
                height: 20,
                width: double.infinity,
                color: Colors.blue,
                child: const Text('2')),
            Container(
                height: 20,
                width: double.infinity,
                color: Colors.blue,
                child: const Text('2')),

            Container(
                height: 200,
                color: Colors.yellow,
                child: const Text('3')),
          ],
        ),
      ),
    );
  }
class BranchComponent extends MultiChildRenderObjectWidget {
  BranchComponent({Key? key,
    required List<Widget> children,
  }) : super(key: key, children: children);

  @override
  RenderObject createRenderObject(BuildContext context) {
    return RenderBranchComponent();
  }
}

class _BranchComponentChild extends ContainerBoxParentData<RenderBox> with ContainerParentDataMixin<RenderBox> {}


class RenderBranchComponent extends RenderBox
    with
        ContainerRenderObjectMixin<RenderBox, _BranchComponentChild>{

  @override
  void setupParentData(covariant RenderObject child) {
    child.parentData = _BranchComponentChild();

  }

  @override
  void performLayout() {
    size = Size(constraints.maxWidth, constraints.minHeight);

    for (var child = firstChild; child != null; child = childAfter(child)) {
      child.layout(
        // limit children to a max height of 50
        constraints
      );
    }
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    var verticalOffset = .0;

    var child = firstChild;
    if(child==null){
      return;
    }

    var first = firstChild;

    for (child = firstChild; child != null; child = childAfter(child)) {
      context.paintChild(child, offset + Offset(50, verticalOffset));

      var nextCursor = childAfter(child);

      var before = childBefore(child);
      if(nextCursor== null){
        bottomCorrect(context.canvas,Offset(offset.dx+5,offset.dy +verticalOffset+child.size.height/2 ),50, 5);
        context.canvas.drawLine(Offset(offset.dx+5, offset.dy +(first?.size.height??0)/2 +15 ), Offset(offset.dx+5,offset.dy +verticalOffset+child.size.height/2-15), paintLine);
      }

      if(before==null){
        topCorrect(context.canvas,Offset(offset.dx+5,offset.dy +verticalOffset+child.size.height/2 ),50, 5);
      }

      if(nextCursor!=null&&before!=null){
        centerNode(context.canvas,Offset(offset.dx+5,offset.dy +verticalOffset+child.size.height/2 ),50, 5);
      }

      verticalOffset += child.size.height;
    }
  }
  final Paint paintLine = Paint()..strokeWidth = 3..style =PaintingStyle.stroke;

  final Paint paintShape = Paint();

  void topCorrect(Canvas canvas, Offset offset, double width, double radius){

    Path path = Path();

    path.moveTo(offset.dx,offset.dy+15);
    path.quadraticBezierTo(offset.dx, offset.dy, offset.dx+15, offset.dy,);
    canvas.drawPath(path, paintLine);

    canvas.drawLine(Offset(offset.dx+15, offset.dy), Offset(offset.dx+20, offset.dy), paintLine);

    canvas.drawCircle(Offset(offset.dx +radius +20, offset.dy), radius, paintShape);
  }

  void centerNode(Canvas canvas, Offset offset, double width, double radius){
    canvas.drawLine(Offset(offset.dx, offset.dy), Offset(offset.dx+20, offset.dy), paintLine);
    canvas.drawLine(Offset(offset.dx, offset.dy+10), Offset(offset.dx, offset.dy-10), paintLine);

    // ve 1 diem tron
    canvas.drawCircle(Offset(offset.dx +radius +20, offset.dy), radius, paintShape);
  }

  void bottomCorrect(Canvas canvas, Offset offset, double width, double radius){
    Path path = Path();
    path.moveTo(offset.dx,offset.dy-15);
    path.quadraticBezierTo(offset.dx, offset.dy, offset.dx+15, offset.dy,);
    canvas.drawPath(path, paintLine);

    canvas.drawLine(Offset(offset.dx+15, offset.dy), Offset(offset.dx+20, offset.dy), paintLine);

    // ve 1 diem tron
    canvas.drawCircle(Offset(offset.dx +radius +20, offset.dy), radius, paintShape);
  }


// @override
  // bool hitTestChildren(BoxHitTestResult result, {required Offset position}) {
  //   // return defaultHitTestChildren(result, position: position);
  // }
  // ...
}

Leave a Comment