diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4b2b266f8..5b6c642c4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,6 @@
+## [62.1.5]
+- [CameraPreview] Fixed custom bottom toolbar content being clipped on compact phone screens (Arena.Mobile #2053).
+
## [62.1.4]
- [Gallery] Fixed issue where only one of multiple image rotations was retained.
diff --git a/src/library/DIPS.Mobile.UI/API/Camera/Preview/CameraPreview.cs b/src/library/DIPS.Mobile.UI/API/Camera/Preview/CameraPreview.cs
index 5ffd515f0..bf0c48219 100644
--- a/src/library/DIPS.Mobile.UI/API/Camera/Preview/CameraPreview.cs
+++ b/src/library/DIPS.Mobile.UI/API/Camera/Preview/CameraPreview.cs
@@ -54,6 +54,7 @@ public Grid ConstructView()
VerticalOptions = LayoutOptions.End,
BackgroundColor = Colors.Transparent,
};
+ m_bottomToolbarContainer.SizeChanged += OnBottomToolbarContainerSizeChanged;
m_topToolbarContainer = new Grid
{
@@ -101,7 +102,7 @@ internal static float ComputeTopToolbarHeight(float width, float frameHeight)
}
///
- /// Here we set the height of the top and bottom toolbar relative to the
+ /// Reserves the camera letterbox area for the toolbars while allowing toolbar content to grow when needed.
///
///
internal void SetToolbarHeights(float frameHeight)
@@ -116,12 +117,9 @@ internal void SetToolbarHeights(float frameHeight)
var topToolbarHeight = ComputeTopToolbarHeight((float)Width, frameHeight);
m_topToolbarContainer.HeightRequest = topToolbarHeight;
- m_bottomToolbarContainer.HeightRequest = Math.Max(totalLetterBoxHeight - topToolbarHeight, 0);
+ m_bottomToolbarContainer.MinimumHeightRequest = Math.Max(totalLetterBoxHeight - topToolbarHeight, 0);
- if (CameraZoomView is not null)
- {
- CameraZoomView.Margin = new Thickness(0, 0, 0, Sizes.GetSize(SizeName.content_margin_small) + m_bottomToolbarContainer.HeightRequest);
- }
+ UpdateCameraZoomMargin();
PreviewView.TranslationY -= topToolbarHeight;
m_hasSetToolbarHeights = true;
@@ -137,13 +135,38 @@ internal double BottomOverlayOffset
get
{
var zoomHeight = CameraZoomView?.Height ?? 0;
- return m_bottomToolbarContainer.HeightRequest
+ return GetBottomToolbarHeight()
+ Sizes.GetSize(SizeName.content_margin_small)
+ zoomHeight
+ Sizes.GetSize(SizeName.content_margin_small);
}
}
+ private void OnBottomToolbarContainerSizeChanged(object? sender, EventArgs e)
+ {
+ if (!m_hasSetToolbarHeights)
+ return;
+
+ UpdateCameraZoomMargin();
+ }
+
+ private void UpdateCameraZoomMargin()
+ {
+ if (CameraZoomView is null)
+ return;
+
+ CameraZoomView.Margin = new Thickness(
+ 0,
+ 0,
+ 0,
+ Sizes.GetSize(SizeName.content_margin_small) + GetBottomToolbarHeight());
+ }
+
+ private double GetBottomToolbarHeight()
+ {
+ return Math.Max(0, Math.Max(m_bottomToolbarContainer.MinimumHeightRequest, m_bottomToolbarContainer.Height));
+ }
+
internal void AddFocusIndicator(float percentX, float percentY)
{
m_grid?.Remove(m_indicatorWrapper);
diff --git a/src/tests/unittests/API/Camera/Preview/CameraPreviewTests.cs b/src/tests/unittests/API/Camera/Preview/CameraPreviewTests.cs
new file mode 100644
index 000000000..d4cefdfc4
--- /dev/null
+++ b/src/tests/unittests/API/Camera/Preview/CameraPreviewTests.cs
@@ -0,0 +1,42 @@
+using System.Linq;
+using DIPS.Mobile.UI.API.Camera.Preview;
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Graphics;
+
+namespace DIPS.Mobile.UI.UnitTests.API.Camera.Preview;
+
+public class CameraPreviewTests
+{
+ [Fact]
+ public void BottomToolbar_CompactScreen_DoesNotClipContent()
+ {
+ // Matches the specimen-scanner frame and bottom content measured on an iPhone SE.
+ const double previewWidth = 375;
+ const double previewHeight = 593;
+ const double bottomContentHeight = 102;
+
+ var cameraPreview = new CameraPreview();
+ var root = cameraPreview.ConstructView();
+ cameraPreview.Content = root;
+ cameraPreview.Measure(previewWidth, previewHeight);
+ cameraPreview.Arrange(new Rect(0, 0, previewWidth, previewHeight));
+ cameraPreview.SetToolbarHeights((float)previewHeight);
+
+ var bottomContent = new Grid
+ {
+ HeightRequest = bottomContentHeight
+ };
+ cameraPreview.AddBottomToolbarView(bottomContent);
+
+ var bottomToolbar = root.Children
+ .OfType()
+ .Single(grid => grid.Children.Contains(bottomContent));
+ var expectedLetterboxHeight = previewHeight
+ - previewWidth / CameraPreview.ThreeFourRatio
+ - CameraPreview.ComputeTopToolbarHeight((float)previewWidth, (float)previewHeight);
+
+ bottomToolbar.HeightRequest.Should().Be(-1);
+ bottomToolbar.MinimumHeightRequest.Should().BeApproximately(expectedLetterboxHeight, 0.01);
+ bottomContent.HeightRequest.Should().BeGreaterThan(bottomToolbar.MinimumHeightRequest);
+ }
+}