getPositionForChild method
Offset
getPositionForChild(
- Size areaSize,
- Size overlaySize
)
override
areaSize 容器尺寸
overlaySize 浮层尺寸
boxSize 目标组件尺寸
position 目标组件中心的坐标
Implementation
@override
Offset getPositionForChild(Size areaSize, Size overlaySize) {
// print("===${areaSize}=====${overlaySize}===${boxSize}==${position}===");
if (onSizeFind != null) {
scheduleMicrotask(() {
onSizeFind!(overlaySize);
});
}
if (clickPosition != null) {
return clickOffset(overlaySize.height, areaSize.height);
}
/// 计算溢出情况
double y = position.dy;
double x = position.dx;
double capacityH = overlaySize.height + boxSize.height / 2 + gap;
double capacityW = overlaySize.width + boxSize.width / 2 + gap;
final OverflowEdge edge = OverflowEdge(
left: x - capacityW < (margin?.left ?? 0),
top: y - capacityH < (margin?.top ?? 0),
right: x + capacityW > areaSize.width,
bottom: y + capacityH > areaSize.height,
);
OverflowAlgorithm? algo = overflowAlgorithm ?? defaultOverflowAlgorithm;
Placement effectPlacement = algo(edge, placement);
if (edge.overflowAll) {
return Offset(
areaSize.width / 2 - overlaySize.width / 2,
areaSize.height / 2 - overlaySize.height / 2,
);
}
Offset center =
position.translate(-overlaySize.width / 2, -overlaySize.height / 2);
double halfWidth = (overlaySize.width - boxSize.width) / 2;
double halfLeftWidth = (overlaySize.width + boxSize.width) / 2 + gap;
double halfHeight = (overlaySize.height - boxSize.height) / 2;
double verticalHeight = (overlaySize.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 + overlaySize.width - areaSize.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) {
result += offsetCalculator!(Calculator(
placement: effectPlacement,
boxSize: boxSize,
overlaySize: overlaySize,
gap: gap));
}
if (effectPlacement != placement || dx != 0) {
scheduleMicrotask(() {
onPlacementShift(PlacementShift(effectPlacement, dx));
});
}
return result;
}