Introduction

Here is a simple example of a YouTube video embeded in an UIWebView. The design is very simple. A stack view inside the mainView. You can find just bellow the design in Xcode. By code, we will instantiate and add the UIWebView in the stack view.

Xamarin IOS Youtube Embed XCode
Xamarin IOS Youtube Embed XCode

By the way, at the end it should look like that.

Xamarin IOS Youtube Embed Design
Xamarin IOS Youtube Embed Design

The most difficult part is to manage the height of the content. Because we can’t have a responsive video and a thumbnail fit in the player. In summary, here is the main steps of the code.

  • Create the UIWebView
  • Generate the Html Request
  • Call YouTube
  • Manage the content size

Step by step

In the first part, we only initialize the UIWebView and the instance is added to the StackView:

_videoWebView = new UIWebView(new CGRect(0, 0, 0, 0));
stackView.AddSubview(_videoWebView);
Code language: YAML (yaml)

We will manage the content size at the end of the loading. It is why we handle the LoadFinished event.

_videoWebView.LoadFinished += VideoWebView_LoadFinished;
_videoWebView.LoadError += _videoWebView_LoadError;

Now, you can call the StartLoad. This method generates the HTML and starts the loading. Firstly, we need the URL of a YouTube video. Be careful the /embed/ part is important. Otherwise you will get errors.

var url = "https://www.youtube.com/embed/Uf-WK-x3tFI";
Code language: C# (cs)

The div is only here for the responsive behavior. We embed the YouTube video via an iFrame. Only the width is specified. We use the maximum space available, the container width. In our case it is the stackview width.

var defaultWidth = stackView.Bounds.Width;

string iFrame = "<div class=\"videoWrapper\"><iframe id=\"" + _FrameId + "\" width=\"" + defaultWidth + "\" src=\"" + url + "\" frameborder =\"0\" allowfullscreen ></iframe></div>";
Code language: HTML, XML (xml)

Finally the LoadHmlString can be call with the HTML.

_videoWebView.LoadHtmlString(html, new NSUrl(url));
Code language: C# (cs)

The next step is the resizing of the content. When the video is loaded, we can calculate the height. In our case, we don’t care about the width because we already know its value. Same as the stackView width. More information about the javascript here.

string jsHeight = "document.documentElement.scrollHeight";
var sFinalHeight = _videoWebView.EvaluateJavascript(jsHeight);
nfloat.TryParse(sFinalHeight, out nfloat finalHeight);
Code language: C# (cs)

Finally, we can apply the calculated height.

_videoWebView.Frame = new CGRect(_videoWebView.Frame.Location, new CGSize(stackView.Frame.Width, finalHeight));
Code language: C# (cs)

The Complete Code

using CoreGraphics;
using Foundation;
using System;
using System.Threading.Tasks;
using UIKit;

namespace VideoApp
{
    public partial class ViewController : UIViewController
    {

        public ViewController(IntPtr handle) : base(handle)
        {
        }

        private int _loadRetry = 0;

        private UIWebView _videoWebView;

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

            _loadRetry = 3;

            _videoWebView = new UIWebView(new CGRect(0, 0, 0, 0));
            stackView.AddSubview(_videoWebView);
  
            _videoWebView.LoadFinished += VideoWebView_LoadFinished;
            _videoWebView.LoadError += _videoWebView_LoadError;

            StartLoad();

        }

        private async void _videoWebView_LoadError(object sender, UIWebErrorArgs e)
        {
            if (_loadRetry <= 0) return;

            _loadRetry--;

            await Task.Delay(100);

            StartLoad();
        }

        private string _FrameId = "youtubeFrame";

        private void StartLoad()
        {
            var url = "https://www.youtube.com/embed/Uf-WK-x3tFI";

            var defaultWidth = stackView.Bounds.Width;
 
           string iFrame = "<div class=\"resp-container\"><iframe class=\"resp-iframe\" id=\"" + _FrameId + "\"  width=\"" + defaultWidth + "\" src=\"" + url + "\" frameborder =\"0\" allowfullscreen ></iframe></div>";


            string html =
                @"
                <!DOCTYPE html>
                <html>
                  <head>
                   <style>
                     .resp-container {
                        position: relative;
                        overflow: hidden;
                        padding-top: 56.25%;
                        height:0;
                    }
                    .resp-iframe {
                        position: absolute;
                        top: 0;
                        left: 0;
                        border: 0;
                        height:100%;
                        width:100%;
                    }
                   </style>
                  </head>
                <body>" + iFrame + @"</body>
                </html>
                ";

            _videoWebView.LoadHtmlString(html, new NSUrl(url));
        }

        public override void ViewDidDisappear(bool animated)
        {
            base.ViewDidDisappear(animated);

            if (_videoWebView != null)
            {
                _videoWebView.LoadFinished -= VideoWebView_LoadFinished;

                _videoWebView.LoadError -= _videoWebView_LoadError;
            }
        }

        private void VideoWebView_LoadFinished(object sender, EventArgs e)
        {
            // Not used here but could be useful
            // The finalWidth == stackView.Frame.Width
            var sFinalWidth = _videoWebView.EvaluateJavascript("document.getElementById(\"" + _FrameId + "\").width");
            nfloat.TryParse(sFinalWidth, out nfloat finalWidth);

            string jsHeight = "document.documentElement.scrollHeight";
            var sFinalHeight = _videoWebView.EvaluateJavascript(jsHeight);
            nfloat.TryParse(sFinalHeight, out nfloat finalHeight);

            _videoWebView.Frame = new CGRect(_videoWebView.Frame.Location, new CGSize(stackView.Frame.Width, finalHeight));

            _videoWebView.LoadFinished -= VideoWebView_LoadFinished;
        }

        public override void DidReceiveMemoryWarning()
        {
            base.DidReceiveMemoryWarning();
        }
    }
}
Code language: C# (cs)

Conclusion

It’s hard to find a good example of a Youtube video embed fit in UIWebView on the Internet. Maybe the solution above is not perfect but at least it’s working 😉

  • I’m not an expert in CSS. So, videoWrapper class coming from this website (Here)
  • Html Iframe on W3Schools
  • The UIWebView documentation

I’m reading a lot of post on stackOverflow and Xamarin Forums. Due to that, It is difficult to list all of them. Anyway, thanks for their contributions 😉

Do you like Xamarin iOS ?

If you like this post don’t forget to have a look to the others previous article.

Happy coding! 🙂