getPositionForChild method

  1. @override
Offset getPositionForChild(
  1. Size size,
  2. Size childSize
)
override

The position where the child should be placed.

The size argument is the size of the parent, which might be different from the value returned by getSize if that size doesn't satisfy the constraints passed to getSize. The childSize argument is the size of the child, which will satisfy the constraints returned by getConstraintsForChild.

Defaults to positioning the child in the upper left corner of the parent.

Implementation

@override
Offset getPositionForChild(Size size, Size childSize) {
  // onSizeFind?.call(childSize);
  if (onSizeFind != null) {
    scheduleMicrotask(() {
      onSizeFind!(childSize);
    });
  }
  if (clickPosition != null) {
    Offset offset = clickPosition!
        .translate(target.dx - boxSize.width / 2, target.dy - boxSize.height / 2);

    /// 底部边界检测
    double bottom = offset.dy+childSize.height - (size.height-gap);
    if(bottom>0){
      offset = offset.translate(0, -bottom);
    }
    return offset;
  }

  bool outBottom = target.dy > size.height - (childSize.height + boxSize.height / 2 + gap);
  bool outTop = target.dy < childSize.height + boxSize.height / 2;
  bool outLeft = target.dx < childSize.width + boxSize.width / 2 + gap;
  bool outRight =
      target.dx > size.width - (childSize.width + boxSize.width / 2 + gap);

  Placement effectPlacement =
      shiftPlacement(outTop, outBottom, outLeft, outRight);

  Offset center =
      target.translate(-childSize.width / 2, -childSize.height / 2);
  double halfWidth = (childSize.width - boxSize.width) / 2;
  double halfLeftWidth = (childSize.width + boxSize.width) / 2 + gap;
  double halfHeight = (childSize.height - boxSize.height) / 2;

  double verticalHeight = (childSize.height + boxSize.height) / 2 + gap;

  Offset translation = switch (effectPlacement) {
    Placement.top => Offset(0, -verticalHeight),
    Placement.topStart => Offset(halfWidth, -verticalHeight),
    Placement.topEnd => Offset(-halfWidth, -verticalHeight),
    Placement.bottom => Offset(0, verticalHeight),
    Placement.bottomStart => Offset(halfWidth, verticalHeight),
    Placement.bottomEnd => Offset(-halfWidth, verticalHeight),
    Placement.left => Offset(-halfLeftWidth, 0),
    Placement.leftStart => Offset(-halfLeftWidth, halfHeight),
    Placement.leftEnd => Offset(-halfLeftWidth, -halfHeight),
    Placement.right => Offset(halfLeftWidth, 0),
    Placement.rightStart => Offset(halfLeftWidth, halfHeight),
    Placement.rightEnd => Offset(halfLeftWidth, -halfHeight),
  };
  Offset result = center + translation;

  double dx = 0;
  double endEdgeDx = result.dx + childSize.width - size.width;
  if (endEdgeDx > 0) {
    result = result.translate(-endEdgeDx, 0);
    dx = -endEdgeDx;
  }
  double startEdgeDy = result.dx;
  if (startEdgeDy < 0) {
    result = result.translate(-startEdgeDy, 0);
    dx = -startEdgeDy;
  }

  if (offsetCalculator != null) {
    // effectPlacement,boxSize,childSize,gap
    result += offsetCalculator!(Calculator(
        placement: effectPlacement,
        boxSize: boxSize,
        overlaySize: childSize,
        gap: gap));
  }

  if (effectPlacement != placement || dx != 0) {
    scheduleMicrotask(() {
      onPlacementShift(PlacementShift(effectPlacement, dx));
    });
  }

  return result;
}