avoid method

Rect avoid(
  1. Rect target,
  2. Rect viewport
)

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;
}