Search code examples
.netxamlwebviewmaui

How to make a WebView only take up the height of its content?


I am porting a very simple Xamarin.Forms application to .NET MAUI (native, not Blazor Hybrid) for mobile and Windows. One page consists just of a WebView taking up all of the viewport as well as a normally transparent ProgressBar laid on top of it (thus the AbsoluteLayout) to indicate the loading process when navigating inside of the WebView.

<AbsoluteLayout x:Name="AbsoluteLayoutFrame" Padding="0" Margin="0">
    <RefreshView x:Name="RefreshView" RefreshColor="#2680ff"
                 AbsoluteLayout.LayoutFlags="All"
                 AbsoluteLayout.LayoutBounds="0,0,1,1"
                 Margin="0">
        <ScrollView x:Name="WebScrollView">
            <WebView x:Name="DigifaiWebView" Margin="0"
                     VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"
                     Navigating="OnNavigating"
                     Navigated="OnNavigated"/>
        </ScrollView>
    </RefreshView>
    ...
</AbsoluteLayout>

I use a RefreshView to trigger a reload of the page in the WebView on a swipe-down gesture.

Initially, WebView was a direct child of the RefreshView (which works well on Android), however, the docs tell me that the child of a RefreshView must be a scrollable element. Sure enough, without it the webview on windows shows a "dead" reload icon and swallows any click events on the top ~150px of the webview.

broken WebView on desktop without ScrollView

Therefore, I added a ScrollView as instructed by the docs. This works great on Windows, but now I have another problem on Android: With the current setup, the WebView on Android takes up way more space in height than it actually needs (-> multiple screens of pure white when scrolling down).

WebView does not stop

I played a lot with XAML properties like VerticalOptions or Height (on the WebView and on the ScrollView), but I just can't get the WebView to shrink down to the size of its HTML content. As I said, the current XAML works perfectly on Windows (even when navigating to much shorter subpages in the Webview), but it leaves these massive amounts of whitespace on Android. Without the ScrollView, it's pretty much the other way round.

How do I resolve this issue? Why does the page on Android even take up so much useless space?


Solution

  • Fyi, I ended up creating a workaround for the problem by building the affected part of the UI in code-behind dynamically based on the target platform using compiler directives.

        private readonly WebView DigifaiWebView = new WebView();
    
        public View()
        {
            InitializeComponent();
            RefreshView.Command = RefreshCommand;
    
            DigifaiWebView.Navigating += OnNavigating;
            DigifaiWebView.Navigated += OnNavigated;
            DigifaiWebView.HorizontalOptions = LayoutOptions.Fill;
            DigifaiWebView.HorizontalOptions = LayoutOptions.Fill;
    
    #if ANDROID
            RefreshView.Content = DigifaiWebView;
    #else
            DigifaiWebView.VerticalOptions = LayoutOptions.Fill;
            ScrollView scrollView = new();
            scrollView.Content = DigifaiWebView;
            RefreshView.Content = scrollView; 
    #endif
            ...
        }
    

    However, it still doesn't feel right, as the MAUI docs claim a RefreshView MUST contain a scrollable element as its direct child and WebView does not seem to be counted as such (or is it on Android?).

    If you have any better idea how to fix this or suspect this is a bug within .NET MAUI, please feel free to tell me.