diff --git a/src/OpenIPC.Viewer.Android/Properties/AndroidManifest.xml b/src/OpenIPC.Viewer.Android/Properties/AndroidManifest.xml index f6990a3..8c342c3 100644 --- a/src/OpenIPC.Viewer.Android/Properties/AndroidManifest.xml +++ b/src/OpenIPC.Viewer.Android/Properties/AndroidManifest.xml @@ -22,7 +22,14 @@ android:roundIcon="@mipmap/icon" android:allowBackup="true" android:supportsRtl="true" - android:name=".MainApplication"> + android:name=".MainApplication" + android:usesCleartextTraffic="true"> + + ApplyResponsiveLayout(e.NewSize.Width); + + private void ApplyResponsiveLayout(double width) { - var width = e.NewSize.Width; + // Width can be 0 before the first arrange (e.g. when called from Loaded). + // A mobile head is always a phone-width viewport, so fall back to the + // mobile layout there — this guarantees the page scrolls and the Majestic + // panel below the video is reachable even if SizeChanged hasn't fired yet. if (width <= 0) - return; + width = OpenIPC.Viewer.App.Services.OverlayDialogPresenter.IsMobile ? 400 : 1000; var videoRow = RootGrid.RowDefinitions[1]; if (width < MobileBreakpoint) { - videoRow.Height = new GridLength(System.Math.Round(width * 9.0 / 16.0)); + var videoHeight = System.Math.Round(width * 9.0 / 16.0); + if (videoHeight < 160) videoHeight = 200; // sane floor before real measure + videoRow.Height = new GridLength(videoHeight); PageScroll.VerticalScrollBarVisibility = Avalonia.Controls.Primitives.ScrollBarVisibility.Auto; } else @@ -89,6 +97,11 @@ private async void OnTalkReleased(object? sender, PointerEventArgs e) private async void OnLoaded(object? sender, RoutedEventArgs e) { + // Engage the responsive layout up front — SizeChanged only fires on a + // change, which on some Android layouts may not happen before the page + // is shown, leaving it in the desktop (fill, no-scroll) state. + ApplyResponsiveLayout(Bounds.Width); + if (Vm is { } vm) await vm.ActivateAsync(CancellationToken.None); }