avoid method
Keep a floating control at its preferred height when a horizontal move clears the camera. Consider vertical positions only when needed.
Implementation
Rect avoid(Rect target, Rect viewport) {
final exclusions = [for (final camera in cutouts) camera.inflate(8)];
if (!exclusions.any(target.overlaps)) return target;
final maxX = math.max(viewport.left, viewport.right - target.width);
final maxY = math.max(viewport.top, viewport.bottom - target.height);
final xs = [
target.left,
for (final camera in exclusions) ...[
camera.left - target.width,
camera.right,
],
];
final ys = [
target.top,
for (final camera in exclusions) ...[
camera.top - target.height,
camera.bottom,
],
];
Rect? best;
var distance = double.infinity;
for (final y in ys) {
for (final x in xs) {
final candidate = Rect.fromLTWH(
x.clamp(viewport.left, maxX),
y.clamp(viewport.top, maxY),
target.width,
target.height,
);
if (exclusions.any(candidate.overlaps)) continue;
final delta = candidate.topLeft - target.topLeft;
// Preserve the bottom alignment of a FAB column where possible.
final score = delta.dx.abs() + delta.dy.abs() * 4;
if (score < distance) {
best = candidate;
distance = score;
}
}
}
return best ?? target;
}