Search code examples
xamarin.formswkwebview

Xamarin.Forms - Strange height issue with my responsive WebViews on iOS


I have a ListView and inside that I want to bind multiple webviews which all vary in height. I want to calculate the height of each webview based on it's content and display it accordingly.

It works on Android - on iOS all WebViews are FAR too big

       await System.Threading.Tasks.Task.Delay(100);
       var result = (double)webView.ScrollView.ContentSize.Height;
       _webView.HeightRequest = result;

The strange thing is: the MORE html characters the webview has, the bigger it gets. So I could add just one character and another 50px will be added to the height.

It is a lot of code to post here but here is a link to the project on github: https://github.com/SlimboTimbo/MultipleWebViews


Solution

  • After checking the project , have found the reason why not works in iOS Device .

    The reason is that the width of webView.ScrollView.ContentSize is not correct , is too small that is 27 . Therefore , it can not show correctly .

    System.Console.WriteLine("----" + resultWidth + "-----"+ resultHeight + "----"+ _webView.Width);
    

    Output :

    2020-06-04 11:19:58.066542+0800 MultipleWebViews.iOS[50674:1690400] ----27-----642----375
    

    Solution :

    You can caluculate the height by the width of HybridWebView, and set the calcualted height for HybridWebView .

    DidFinishNavigation method code as follow :

    public override async void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
    {
    
        try
        {
            var _webView = webViewRenderer.Element as HybridWebView;
            if (_webView != null)
            {
                await System.Threading.Tasks.Task.Delay(100);
                var resultWidth = (double)webView.ScrollView.ContentSize.Width;
                var resultHeight = (double)webView.ScrollView.ContentSize.Height;
                System.Console.WriteLine("----" + resultWidth + "-----"+ resultHeight + "----"+ _webView.Width);
    
                double result = MeasureTextHeightSize(_webView.messageContent, _webView.Width, UIFont.LabelFontSize, null);
    
                _webView.HeightRequest = result;
    
                MessagingCenter.Send<Object, PassModel>(this, "LoadFinished", new PassModel(_webView.Id, Convert.ToDouble(result)));
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error at HybridWebViewRenderer LoadingFinished: " + ex.Message);
        }
    }
    

    MeasureTextHeightSize ( Calculate the height method )

    private double MeasureTextHeightSize(string text, double width, double fontSize, string fontName = null)
    {
        var nsText = new NSString(text);
        var boundSize = new SizeF((float)width, float.MaxValue);
        var options = NSStringDrawingOptions.UsesFontLeading | NSStringDrawingOptions.UsesLineFragmentOrigin;
    
        if (fontName == null)
        {
            fontName = "HelveticaNeue";
        }
    
        var attributes = new UIStringAttributes
        {
            Font = UIFont.FromName(fontName, (float)fontSize)
        };
    
        var sizeF = nsText.GetBoundingRect(boundSize, options, attributes, null).Size;
    
        //return new Xamarin.Forms.Size((double)sizeF.Width, (double)sizeF.Height);
        return (double)sizeF.Height;
    }
    

    The Effect :

    enter image description here

    Note : You can modify the fontSize of this method according to your current system font size . And also can custom the return value ,such as return (double)sizeF.Height + 10 to fit screen .