locked
iOS WebView doesn't resize Width on device rotation. RRS feed

  • Question

  • User28549 posted

    When I drop a WebView into a view, I'm having an issue whereby when I rotate the device, the WebView stays the same width as it was initially.

    note: I always start out vertical, so rotating horizontal shows a narrow WebView

            var webView = new WebView
            {
                Source = new HtmlWebViewSource { Html = segment.ContentHtml },
                VerticalOptions = LayoutOptions.FillAndExpand,
                HorizontalOptions = LayoutOptions.FillAndExpand,
                HeightRequest = 250
            };
    

    Is this a bug?

    Monday, July 14, 2014 5:34 PM

All replies

  • User10166 posted

    You need to create a custom render for the webview, and in the OnElementChanged event add:

            this.AutoresizingMask = UIViewAutoresizing.FlexibleDimensions;
    
    Monday, July 14, 2014 6:47 PM
  • User28549 posted

    ah interesting. Is this a logged bug then, because building a Custom Render for such a thing seems a little bit odd.

    Monday, July 14, 2014 7:57 PM
  • User3932 posted

    @ChaseFlorell?, you will run into issues which need a custom webview renderer five minutes after you solve this one :) So don't mind creating the custom renderer. You can copy/paste code from the WebView docs (workaround for baseurl).

    @ChristineBlanda?, maybe you did some more? As it does not work for me, and from my memory for UIWebview you have to reload the content, because otherwise the content is scaled to the new size instead of a full relayout.

    Tuesday, July 15, 2014 6:22 AM
  • User10166 posted

    @HugoLogmans? I do a number of other things in the custom render, but not related to the size. I do set ScalesPageToFit=true but it doesn't appear to have an effect.

    Tuesday, July 15, 2014 12:09 PM
  • User17914 posted

    No luck here either. Only reloading content, or re-adding webview to layout works for me.

    Interestingly, in a native IOS app, the problem goes away if the UIWebView instance is the main view of a UIWebViewController. http://stackoverflow.com/questions/4125316/uiwebview-rotate-content

    Sunday, August 3, 2014 2:34 AM
  • User69840 posted

    I found that setting the UIAutoResizingMask only worked for the parent view, not the internal webview. In my case even with reloading the webview, the internal view was always 1024 wide on iPad regardless of orientation (although it would load to portrait size initially, sometimes I could scroll past that to the full 1024).

    I've fixed this by resizing the WebView's non-UIImageView (it has two small ones, at least on my page) to the same size as its parent, after the orientation change has occurred.

    This is really hacky, but is working great:

    private void ResizeSubviewsToParent() { foreach (UIView subview in Subviews) { foreach (UIView sub in subview.Subviews) { if ((sub is UIImageView) == false) { sub.Frame = new RectangleF(sub.Frame.X, sub.Frame.Y, subview.Frame.Width, sub.Frame.Height); } } } }

    Edit: I found that on pages longer than the screen height the bottom would be cut off the first time I show a webview, so I changed this to only modify the width of the subview's subview which seems to work fine across all pages in my app on both iPhone and iPad.

    Wednesday, October 29, 2014 2:47 AM
  • User95002 posted

    I know this thread is old but I've tried everything to get this to work and I found one solution after realizing the problem is also present if you develop for native apps. The solution is to put a tag in the head section of the page. meta name=""viewport"" content=""width=device-width,height=device-height"" Note I had to remove the < and /> from the comment because otherwise this forum cut it off. I know some of you may not have control over the page you are viewing or it may be viewed from other devices but maybe in those cases you can use javascript to inject the content into the head section. Either way it worked great no other modifications required.

    Friday, February 13, 2015 4:56 PM
  • User53292 posted

    @ChristineBlanda - THANK YOU! I think FlexibleDimensions was the help I needed - also doing it onchange not just on load.

    Sunday, March 22, 2015 4:09 PM
  • User109298 posted

    @KeithRowe , @ChristineBlanda Hi, I can't make it work when i rotate my iphone 5C screen, the webview width don't change at all.

    Here is my customwebviewrender :

    using Xamarin.Forms.Platform.iOS;
    using app.iOS;
    using app;
    using Xamarin.Forms;
    using UIKit;
    
    [assembly: ExportRenderer (typeof (CustomWebView), typeof (CustomWebViewRenderer))]
    namespace app.iOS
    {
        public class CustomWebViewRenderer : WebViewRenderer
        {
            // Override the OnElementChanged method so we can tweak this renderer post-initial setup
            protected override void OnElementChanged (VisualElementChangedEventArgs e)
            {
                base.OnElementChanged (e);
    
                var webView = this;
                webView.AutoresizingMask = UIViewAutoresizing.FlexibleDimensions;
                webView.ScalesPageToFit = true;
            }
    
    
        }
    }
    

    Any idea of the problem?

    Tuesday, March 24, 2015 9:58 AM
  • User53292 posted

    @ElielDinaully - I'm not positive, but it may be that you need to apply these to the base view hosting the webview as well.

    Tuesday, March 24, 2015 12:50 PM
  • User109298 posted

    @KeithRowe

    Can't get it at all.

    I have a ContentPage, with a custom stacklayout with my webview in :

    var stack = new CustomStackLayout { Padding = 0, Orientation = StackOrientation.Vertical, VerticalOptions = LayoutOptions.FillAndExpand, HorizontalOptions = LayoutOptions.FillAndExpand };

    The CustomStackLayoutRenderer in iOS :

    public class CustomStackLayoutRenderer : VisualElementRenderer<StackLayout> { // Override the OnElementChanged method so we can tweak this renderer post-initial setup protected override void OnElementChanged (Xamarin.Forms.Platform.iOS.ElementChangedEventArgs<Xamarin.Forms.StackLayout> e) { base.OnElementChanged (e); Console.WriteLine ("is called"); this.AutoresizingMask = UIViewAutoresizing.FlexibleDimensions; }
    }

    and my webview is then added to the stacklayout :

    CustomWebView webView = new CustomWebView {
                    Source = new HtmlWebViewSource {
                        Html = d.description
                    }, 
                    VerticalOptions = LayoutOptions.FillAndExpand,
                    HorizontalOptions = LayoutOptions.FillAndExpand
                };
    stack.Children.add(webview);
    
    Content = stack;
    

    And when i rotate to landscape, same problem... Doesn't fill the screen, i may be missing something or not doing it well at all.

    Tuesday, March 24, 2015 1:34 PM
  • User23126 posted

    Hey Guys, it seems that we may have a similar problem, may you can take a look at my issue too: forums.xamarin.com/discussion/comment/111959 We would appreciate any help!!! Thanky in advance!

    Wednesday, March 25, 2015 4:46 PM
  • User94701 posted

    @ChristineBlanda Hi how would I go about creating a custom render for WebView

    Tuesday, March 31, 2015 12:59 PM
  • User94701 posted

    Just added the autoresizeingMask and it worked. Thanks @ChristineBlanda

            var webView = new UIWebView(View.Bounds);
            webView.ScalesPageToFit = true;
            **webView.AutoresizingMask = UIViewAutoresizing.FlexibleDimensions;**
            string url = "WEBSITE.COM";
            webView.LoadRequest(new NSUrlRequest(new NSUrl(url)));
    
            View.AddSubview(webView);
    
    Tuesday, March 31, 2015 1:14 PM
  • User53292 posted

    OK, had used this for a different custom renderer (local video player). Now implementing Xamarin.Forms webview and having the same problems. Are people re-writing the Forms webview into a custom renderer because it does not have the rotation down? Or is there a solution for the Forms Webview?

    Wednesday, April 1, 2015 7:30 PM
  • User69196 posted

    I'm having the same problem with a custom WebViewRenderer. Setting AutoresizingMask = UIViewAutoresizing.FlexibleDimensions; has no effect. When I rotate to landscape, the right half of the screen is black. Has anyone gotten this to work?

    Tuesday, May 12, 2015 9:30 PM
  • User89714 posted

    I know this is a long-running thread, and we can find ways to make this work, but this should be sorted in the Xamarin iOS support in XF. I've raised bug 30297 as I couldn't find an existing bug for this in Bugzilla.

    Thursday, May 21, 2015 9:33 AM
  • User62178 posted

    I was having issues with this as well, and I've tried every suggestion that was made here without success.

    After looking a bit further I found out that manipulating the Bounds of the NativeView was successfull. Since my WebView is fullscreen the following implementation of LayoutSubviews did the trick: public override void LayoutSubviews () { base.LayoutSubviews (); NativeView.Bounds = UIKit.UIScreen.MainScreen.Bounds; }

    However this does only work when you have a fullscreen webview. Haven't tried to get it to work with a WebView that's not fullscreen yet.

    Hoping to see the issue fixed soon because all of these hacks are annoying. Thanks for the bug report @JohnHardman! And just for reference: https://bugzilla.xamarin.com/show_bug.cgi?id=30297

    Saturday, June 27, 2015 1:16 PM
  • User73674 posted

    Did anyone find a workaround to handle this isue? ( WebView does not resize on iOS when change orientation)

    I have also problems in Loading the page the first time (without changing orientation) After Reloading, everything seems to be fine...

    I think it is an timing issue, when the page is originally loaded, and the onchanges event (in the webviewpagerenderer) is a little to late... After reloading (it is coming out of the cache) and everything is fine...

    Any ideas?

    Thanks, Gerhard

    Wednesday, July 15, 2015 10:05 AM
  • User122934 posted

    @TimKlingeleers This works great, but I am hoping you might be able to help me figure out how to subtract UIKit.UIScreen.MainScreen.Bounds from the height of the Nav Bar on the screen. I found UIKit.UIScreen.MainScreen.ApplicationFrame which subtracts the bounds of the status bar, but I cannot seem to figure out how to get the bounds of the Nav Bar when the view is within a NavigationPage.

    Otherwise the only thing that has worked for me is to refresh the WebView using UIWebView.Refresh() but even that makes everything look weird until you click a new link so it is not a great solution.

    Thursday, August 27, 2015 1:14 PM
  • User62178 posted

    @hvaughan I did not test this but you should be able to get the height of the navigation bar from NavigationController.NavigationBar.Frame.Height from within your iOS renderer. Please keep in mind to check for null's on the NavigationController property.

    Let me know if this helped you, otherwise I'll try to investigate further if time permits.

    Thursday, August 27, 2015 2:14 PM
  • User2496 posted

    Hey guys we have fixed this issue.. should be available in 1.5.1-pre1 when it's released.

    Thursday, August 27, 2015 2:24 PM
  • User122934 posted

    @TimKlingeleers Well I am not sure how to get NavigationController from my WebViewRenderer but I did find this site saying that the Navigation Bar is always 44 pts. So subtracting that from Bounds.Height does do the trick for now. But I am glad the they were finally able to fix it! Thanks for your help.

    http://www.idev101.com/code/User_Interface/sizes.html

    Thursday, August 27, 2015 9:18 PM
  • User62178 posted

    Oh you are right @hvaughan, NavigationController isn't directly accessible from a WebViewRenderer. I was mixing it up with the PageRenderer base class.

    By the way, the Navigation Bar can also be 32 pts when in landscape mode. In portrait it's 44 pts indeed. However keep in mind that these numbers can change in future versions of the OS.

    Good to see the issue get fixed in 1.5.1-pre1!

    Thursday, August 27, 2015 9:32 PM
  • User122934 posted

    All, I was able to fix this issue by setting the WebView's HeightRequest and WidthRequest to the ContentPage/ContentView's Height and Width from within the SizeChanged event, which should get called on device Orientation.

    ContentPage's Constructor:

    SizeChanged += (sender, arg) => {
        Padding = new Thickness(0, Height > Width ? 10 : 5, 0, 0);
    
        WebViewItem.HeightRequest = Height;
        WebViewItem.WidthRequest  = Width;
    };
    

    I also fixed another slightly related issue with the iOS WebView. The issue happened when a user clicked a 'Refresh' Button in the app, which would set the WebView's Source property to a new HtmlWebViewSource. The first time a user would click the 'Refresh' Button, the WebView would be completely blank and would not show any content. If the user clicked the Button again, the data would show up normally again.

    To fix this, I am now changing the WebView's Source property, removing the WebView from it's parent StackLayout, and then re-adding the WebView back to the StackLayout.

    Part of a method that eventually gets run when the 'Refresh' button is clicked:

    WebView clickedOnWebView = (WebView)clickedOnStackLayout.Children.FirstOrDefault();
    Device.BeginInvokeOnMainThread(() => {
        clickedOnWebView.Source = new HtmlWebViewSource { Html = newHtmlData };
        clickedOnStackLayout.Children.RemoveAt(0);
        clickedOnStackLayout.Children.Add(clickedOnWebView);
    });
    
    Saturday, September 26, 2015 10:56 PM
  • User162621 posted

    @rmarinho , I don't think this issue is fixed. I am using Xamarin.Forms 1.5.1.6468 and I am changing webview's width & height on device orientation change in OnSizeAllocated method. But its not working. I am testing in iOS devices 6.1 & 8.4. @TimKlingeleers solution is working in 8.4 device. But in 6.1 device, width is not expanding in landscape mode. Its positioning in center of the page.

    How to fix it?

    Monday, October 26, 2015 8:15 AM
  • User2496 posted

    Hi @SubhaMuralidharan.6484 correct it isn't fixed yet. We got a solution working but it broke other behaviours so we didn't release that fix. Will provide info on the bugzilla issue when we have a fix ready again.

    Monday, October 26, 2015 10:51 AM
  • User46653 posted

    Hi @rmarinho, this is not working in Xamarin.Forms Version 2.0.0.6484 either, is there any chance of you posting a complete interim Renderer solution codebase that caters for both iOS and Android, we've been putting the release of our Xamarin Forms SDK off for a while for problems like these but we've got to get it out by December 4?

    Wednesday, November 25, 2015 2:46 PM
  • User122934 posted

    @AnthonyHarrison.3194

    The following code does work if you put it into a custom WebView renderer on iOS (there is not an issue with rotation on Android). It is a little quirky immediately after rotation but as soon as a user clicks a link in the WebView everything looks normal again. This is what I am currently using as we could not wait on a real fix. Definitely let me know if you need help with it.

    /// <summary>
    /// Doing this below because of this BUG: Known iOS WebView issue when rotating: https://forums.xamarin.com/discussion/20418/ios-webview-doesnt-resize-width-on-device-rotation & https://bugzilla.xamarin.com/show_bug.cgi?id=30047
    /// </summary>
    public override void LayoutSubviews() {
        base.LayoutSubviews();
        CGRect bounds     = UIScreen.MainScreen.Bounds;
        bounds.Height     = bounds.Height - 60;
        NativeView.Bounds = bounds;
    }
    
    Wednesday, November 25, 2015 6:46 PM
  • User46653 posted

    Thanks hines, that's excellent! We've got a User Story where some content wont have links, so after some discussion the Product Owner decided to put the iOS WebView into the release as is, knowing that the user will just manually resize it themselves; in our case it's just come down to letting it through under the Known Issues category. Thanks for your help, though, it's bookmarked as our go-to workaround where content will contain links, etc.

    Friday, November 27, 2015 8:30 AM
  • User46653 posted

    For the benefit of others, we did find that the following renderer does work, so long as you want the WebView fullscreen (however in our SDK we aren't to know how integrators will use it, hence abandoned it). But it does work per se:

        public class OurWebViewRenderer : WebViewRenderer
        {
            public OurWebViewRenderer()
            {
                this.ScalesPageToFit = true;
                this.AutoresizingMask = UIKit.UIViewAutoresizing.FlexibleDimensions;
            }
    
            protected override void OnElementChanged(VisualElementChangedEventArgs e)
            {
                base.OnElementChanged(e);
    
           // just to illustrate that the source action is happening in the Forms webview
                OurWebView owv = (OurWebView)this.Element;
                var temp = owv.HtmlString;
    
            }
    
            public override void LayoutSubviews()
            {
                base.LayoutSubviews();
                NativeView.Bounds = UIKit.UIScreen.MainScreen.Bounds;
            }
        }
    

    Naturally the above must be decorated with the following - OUTSIDE the namespace, not inside:

    [assembly: ExportRendererAttribute(typeof(OurWebView), typeof(OurWebViewRenderer))]

    And this is the Forms WebView:

    public class OurWebView : WebView
    {
        public static readonly BindableProperty HtmlStringProperty =
            BindableProperty.Create<OurWebView, string>(ctrl => ctrl.HtmlString,
            defaultValue: string.Empty,
            defaultBindingMode: BindingMode.TwoWay,
            propertyChanging: (bindable, oldValue, newValue) =>
            {
                var ctrl = (OurWebView)bindable;
                ctrl.HtmlString = newValue;
            });
    
            public string HtmlString
            {
                get { return (string)base.GetValue(HtmlStringProperty); }
                set { base.SetValue(HtmlStringProperty, value); }
            }
    
        public OurWebView()
        {
            this.PropertyChanged += (s, e) =>
                {
                    if (e.PropertyName.Equals(OurWebView.HtmlStringProperty.PropertyName))
                    {
                        var htmlSource = new HtmlWebViewSource();
                        htmlSource.Html = HtmlString;
    
                        this.Source = htmlSource;
                    }
                };
        }
    
    }
    
    Friday, November 27, 2015 8:44 AM
  • User241403 posted

    Hi, heres my solution, I was having a similar problem when rotating Ipad or Iphone, the page inside the UIWebView was fine, but the frame of the component kept it original size. My solution: Override the method DidRotate of ViewController and resize every subview: public override void DidRotate(UIInterfaceOrientation fromInterfaceOrientation) { foreach (UIView view in View.Subviews) { view.Frame = View.Bounds; }
    base.DidRotate(fromInterfaceOrientation); }

    Wednesday, July 27, 2016 6:35 PM
  • User149548 posted

    status update: this is still broken

    Monday, September 25, 2017 5:31 PM
  • User122934 posted

    @KingChrisCole It has been working for me for some time now. Add some code if it is not for you.

    Monday, September 25, 2017 5:35 PM
  • User149548 posted

    @hvaughan

    No thanks, I've banged my head against the wall with this for long enough - I'm just going to try a different route.

    Monday, September 25, 2017 5:38 PM