UIWebView rotating problem

Hi,

I have a simple application with one UIScrollView and one UIWebView. The UIWebView is embedded inside the UIScrollView. Everything works great except if I rotate the device, the UIWebView doesn't automatically readjust. I am not using storyboards or xcode to manage my layout. Could somebody please suggest some code that I could use to fix this issue?

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();

        Title = "Test WebView";
        View.BackgroundColor = UIColor.White;

        scrollView = new UIScrollView (View.Bounds);

        webView = new UIWebView(View.Bounds);

        scrollView.AddSubview (webView);

        View.AddSubview(scrollView);

        string url = "http://www.google.com";
        webView.LoadRequest (new NSUrlRequest (new NSUrl (url)));

        // if this is false, page will be 'zoomed in' to normal size
        // webView.ScalesPageToFit = true;
    }

Cheers,
Zam

Posts

  • adamkempadamkemp mod USInsider, Developer Group Leader mod

    UIWebView already handles its own scrolling so you don't need your own scroll view. Just add your web view directly to your view and then add this line:

    webView.AutoresizingMask = UIViewAutoresizing.All;
    
  • ZamilMurji.6595ZamilMurji.6595 CAMember

    Thanks Adam. Your suggestion works if in AppDelegate.cs window object RootViewController is set like so:

    window.RootViewController = navigationController;

    Initially I started with a project that did not do this and instead added a subview to the window like so:

    window.AddSubview (navigationController.View);

    Why is that?

    Also, your suggestion is a million times cleaner then the solution that I found to work. I'm copying it below for future reference should anybody care to see it.

            public override void ViewDidLoad ()
            {
                base.ViewDidLoad ();
    
                Title = "Test WebView";
                View.BackgroundColor = UIColor.White;
    
                webView = new UIWebView (View.Bounds);
                string url = "http://www.google.com";
                webView.LoadRequest (new NSUrlRequest (new NSUrl (url)));
    
                // if you're using your solution, then you can comment out this call 
                // call our helper method to position the controls
                PositionControls (InterfaceOrientation);
    
                View.AddSubview (webView);
    
                // This is the line of code that you suggested that will work and you can comment out the 3 methods below 
                // if you choose to use it
                // webView.AutoresizingMask = UIViewAutoresizing.All;
    
                // if this is false, page will be 'zoomed in' to normal size
                // webView.ScalesPageToFit = true;
            }
    
            public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
            {
                // we're passed to orientation that it will rotate to. in our case, we could
                // just return true, but this switch illustrates how you can test for the 
                // different cases
                switch (toInterfaceOrientation) {
                case UIInterfaceOrientation.LandscapeLeft:
                case UIInterfaceOrientation.LandscapeRight:
                case UIInterfaceOrientation.Portrait:
                case UIInterfaceOrientation.PortraitUpsideDown:
                default:
                    return true;
                }
            }
    
            public override void WillAnimateRotation (UIInterfaceOrientation toInterfaceOrientation, double duration)
            {
                base.WillAnimateRotation (toInterfaceOrientation, duration);
    
                // call our helper method to position the controls
                PositionControls (toInterfaceOrientation);
            }
    
            protected void PositionControls (UIInterfaceOrientation toInterfaceOrientation)
            {
                switch (toInterfaceOrientation) {
                case UIInterfaceOrientatßion.LandscapeLeft:
                case UIInterfaceOrientation.LandscapeRight:
                    webView.Frame = new RectangleF (0, 0, Math.Max (View.Bounds.Width, View.Bounds.Height), Math.Min (View.Bounds.Width, View.Bounds.Height));
                    break;
                case UIInterfaceOrientation.Portrait:
                case UIInterfaceOrientation.PortraitUpsideDown:
                    webView.Frame = new RectangleF (0, 0, Math.Min (View.Bounds.Width, View.Bounds.Height), Math.Max (View.Bounds.Width, View.Bounds.Height));
                    break;
                }
            }
    
  • adamkempadamkemp mod USInsider, Developer Group Leader mod

    It looks like you had some old code or learned from old examples. A long time ago you had to add your main view controller's View to the window yourself. Now you only have to assign it as the RootViewController of the window. Once you do that the rotation and other notifications will be delivered to that view controller.

    You also quoted code using ShouldAutorotateToInterfaceOrientation and WillAnimateRotation. Those are each deprecated now (the latter just in iOS 8, but often unnecessary even prior to that). Instead you can use GetSupportedInterfaceOrientations and ViewWill/DidLayoutSubviews.

  • ZamilMurji.6595ZamilMurji.6595 CAMember

    Thanks Adam. I'll keep that in mind when going forward.

  • EmanEman ✭✭ USMember ✭✭

    Hi, I added the said line but its not taking effect.. here is my code:

    webView.ContentMode = UIViewContentMode.ScaleAspectFit;
    webView.ScalesPageToFit = true;
    webView.AutoresizingMask = UIViewAutoresizing.All;

    My webview is just inside a ViewController and no other elements inside, when I rotates nothing happens.

  • adamkempadamkemp mod USInsider, Developer Group Leader mod

    That's not enough information. I would guess that your entire view controller isn't rotating, which may be an issue with the app delegate or with the view controller itself. If you'll post a sample project that reproduces the issue I can take a look.

  • ChristineZuckermanChristineZuckerman ✭✭✭ USMember ✭✭✭

    @adamkemp I'm also having trouble getting this to work with the latest version of forms (I know it was working in a previous version). I've been using the sample code WorkingWithWebview as a test project, and added the following code to the renderer:

        public BaseUrlWebViewRenderer()

        {

            this.ScalesPageToFit = true;

            this.AutoresizingMask = UIViewAutoresizing.All;

        }


        protected override void OnElementChanged (VisualElementChangedEventArgs e)

        {

            base.OnElementChanged (e);
    

    
 this.ScalesPageToFit = true;

    this.AutoresizingMask = UIViewAutoresizing.All;

    }


    am I doing something wrong?
    Thanks!

  • adamkempadamkemp mod USInsider, Developer Group Leader mod

    You shouldn't be setting this.AutoresizingMask. The size and position of a view is determined by its owner, not itself (see here for an explanation).

    For a Forms WebView you should be using the Forms layout system. By default a WebView should fill its container so maybe you're doing something that confuses it. Maybe you're putting it in a StackLayout?

  • ChristineZuckermanChristineZuckerman ✭✭✭ USMember ✭✭✭

    @adamkemp I pulled back to the simplest web view and it is still not resizing on rotation. MainPage is the WebView in a Content Page with nothing else:

        public App ()
        {
            MainPage = new WebPage ();
        }
    
    public class WebPage : ContentPage
    {
        public WebPage ()
        {
            var browser = new WebView();
            browser.Source = "http://xamarin.com";
            Content = browser;
        }
    }
    

    Do you have any examples where it is working? Thanks!

  • adamkempadamkemp mod USInsider, Developer Group Leader mod

    The view itself rotated correctly, but the page didn't re-render at a different size.

  • ChristineZuckermanChristineZuckerman ✭✭✭ USMember ✭✭✭

    @adamkemp OK, that makes sense because if I open something on the page it paints full width. So how do I get it to re-render the page on rotation?

  • adamkempadamkemp mod USInsider, Developer Group Leader mod

    I don't know. If you figure out how to do it in a non-Forms application then you can probably use a custom renderer to make it behave the same in Forms.

  • ChristineZuckermanChristineZuckerman ✭✭✭ USMember ✭✭✭

    Am I missing something? I would expect this to be a common, expected behavior. On the Android side it just behaves this way.

  • adamkempadamkemp mod USInsider, Developer Group Leader mod

    This appears to be the same behavior as a stock UIWebView. In your previous posts you were trying to use a custom renderer to set ScalesPageToFit to true. I think that's an appropriate thing to do if this is the behavior you want.

  • ChristineZuckermanChristineZuckerman ✭✭✭ USMember ✭✭✭

    Except it isn't working ... so am I doing something wrong or is this just not working as expected?

  • adamkempadamkemp mod USInsider, Developer Group Leader mod

    I've seen too many versions of your code to know exactly what you're trying at this point. Could you upload a .zip showing the exact thing you're trying now?

  • ChristineZuckermanChristineZuckerman ✭✭✭ USMember ✭✭✭

    It's all the same code, a very simple test of the webview to get the webview to fill the view properly on rotation, based on the Xamarin WorkingWithWebviews sample. I modified the App to only call the WebPage:

    namespace WorkingWithWebview
    {
        public class App : Application // superclass new in 1.3
        {
            public App ()
            {
                MainPage = new WebPage ();
            }
        }
    }
    

    The WebPage is just a ContentPage with the Webview:

    namespace WorkingWithWebview
    {
    
        public class WebPage : ContentPage
        {
            public WebPage ()
            {
                var browser = new TestWebView {Source = "http://xamarin.com"};
    //          var browser = new WebView();
    
                Content = browser;
            }
        }
    }
    

    Then I've added a Rendeerer in iOS to add ScalesPageToFit:

    namespace WorkingWithWebview.iOS
    {
        [assembly: ExportRenderer(typeof (TestWebView), typeof(TestWebViewRenderer))]
        public class TestWebViewRenderer : WebViewRenderer
        {
            public TestWebViewRenderer()
            {
                this.ScalesPageToFit = true;
            }
            protected override void OnElementChanged(VisualElementChangedEventArgs e)
            {
                base.OnElementChanged(e);
                this.ScalesPageToFit = true;
            }
        }
    }
    

    And to tie them together:

    namespace WorkingWithWebview
    {
        public class TestWebView : WebView
        {
        }
    }
    

    If you have an example that does this I'd love to see it.

  • adamkempadamkemp mod USInsider, Developer Group Leader mod

    Could you just put that code in a .zip so I can run it? I've found that doing that step myself can overlook other things that people might have done wrong, and it's more reliable to take the exact code they're running without introducing any of my own assumptions.

  • ChristineZuckermanChristineZuckerman ✭✭✭ USMember ✭✭✭

    Sure, here

  • adamkempadamkemp mod USInsider, Developer Group Leader mod

    It seems that you didn't give me all of the projects. I'm missing the platform-specific projects.

  • ChristineZuckermanChristineZuckerman ✭✭✭ USMember ✭✭✭

    Sorry, its organized different than I'm used to.

  • adamkempadamkemp mod USInsider, Developer Group Leader mod

    I think this is a bug in the default WebViewRenderer. I haven't quite worked out what is causing it, but this looks suspicious:

        public override void LayoutSubviews()
        {
            base.LayoutSubviews();
            this.ScrollView.Frame = this.Bounds;
        }
    

    I created this bug report.

Sign In or Register to comment.