Show iframe video in full screen using Forms CustomRenderer webview on Android

In a Forms app we use a custom WebViewRenderer in the .Droid project to display html that contains videos embedded in <iframe>.

I'm having trouble making these videos go into full screen when the user pushes the button to toggle full screen in the video player.

I'm trying to use WebChromeClient, as per Xamarin's WebView full screen advise to toggle full screen mode. However, I'm not sure how to go about this. I have tried to port a Java implementation of WebChromeClient but I just get a blank screen after OnShowCustomView(View view, ICustomViewCallback callback) has finished executing.

Here's the code (I think is relevant), let me know if I'm missing important pieces.

CustomRenderer for WebView:

 public class MyWebViewRenderer : WebViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
        {
            base.OnElementChanged(e);

                        var activity = this.Context as Activity;
                        var view = activity.LayoutInflater.Inflate(Resource.Layout.fullScreenVideoLayouts, this, false);
                        ViewGroup videoViewLayout = (ViewGroup) view.FindViewById(Resource.Id.videoLayout);
                        View nonVideoLayout = view.FindViewById(Resource.Id.nonVideoLayout);

                        control.SetWebChromeClient( new WebViewWebChromeClient(nonVideoLayout, videoViewLayout));
            }               
        }

Custom VideoEnabledWebChromeClient:

 private class WebViewWebChromeClient : WebChromeClient
    {
        private View _activityNonVideoView;
        private ViewGroup _activityVideoView;
        private bool _isVideoFullscreen; // Indicates if the video is being displayed using a custom view (typically full-screen)
        private FrameLayout _videoViewContainer;
        private ICustomViewCallback _videoViewCallback;

        public WebViewWebChromeClient() { }

        public WebViewWebChromeClient(View view, ViewGroup formsViewGroup)
        {
            this._activityNonVideoView = view;
            this._activityVideoView = formsViewGroup;
        }

        public override void OnShowCustomView(View view, ICustomViewCallback callback)
        {
            base.OnShowCustomView(view, callback);

            FrameLayout frameLayout = view as FrameLayout;

            _isVideoFullscreen = true;
            _videoViewContainer = frameLayout;
            _videoViewCallback = callback;

            // Hide the non-video view, add the video view, and show it
            _activityNonVideoView.Visibility = ViewStates.Invisible;
            _activityVideoView.AddView(_videoViewContainer, new ViewGroup.LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent));
            _activityVideoView.Visibility = ViewStates.Visible;
         }

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

            if (_isVideoFullscreen)
            {
                // Hide the video view, remove it, and show the non-video view
                _activityVideoView.Visibility = ViewStates.Invisible;
                _activityVideoView.RemoveView(_videoViewContainer);
                _activityNonVideoView.Visibility = ViewStates.Visible;

                if (_videoViewCallback != null)
                {
                    _videoViewCallback.OnCustomViewHidden();
                }

                _isVideoFullscreen = false;
                _videoViewContainer = null;
                _videoViewCallback = null;
            }
        }
    }

Inflated .axml file (ported from original):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  <!-- View that will be hidden when video goes fullscreen -->
    <RelativeLayout
        android:id="@+id/nonVideoLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- View where the video will be shown when video goes fullscreen -->
    <RelativeLayout
        android:id="@+id/videoLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/> >
</RelativeLayout>

I am very new to Xamarin and Android development so I might be going about this all wrong. Please let me know if there are other ways of handling this much easier. I'm forced to use this setup with WebView and videos in iframe's but other things I'm not aware of might be possible to change. Any help is much appreciated.

Best Answer

  • MuhammadHaggagMuhammadHaggag US ✭✭
    Accepted Answer

    I apologize for the delay. Life happened :)

    I created a github repository with a sample implementation here:
    github.com/mhaggag/XFAndroidFullScreenWebView
    (The forum software won't allow me to post links from a new account, sorry)

Answers

  • y_SBSICy_SBSIC USMember ✭✭

    Hi @JesperBaltzersen did you find any solution for this, I am also stuck in fullscreen functionality. please share the solution if you have find. Thanks

  • JesperBaltzersenJesperBaltzersen DKUniversity ✭✭

    Hi @Ajay_SBSIC. No, unfortunately I didn't. It was dropped after spending too much time on it. I will update this thread if we get back to it and actually solve it. I hope you will do the same if you find a solution:-)

  • y_SBSICy_SBSIC USMember ✭✭

    Ok Thanks and Yes, of course I will update if I got any solution

  • PedroCondePedroConde PTMember ✭✭
    edited May 2017

    @Ajay_SBSIC @JesperChristensen, have you found any solution for the reported issue?

  • y_SBSICy_SBSIC USMember ✭✭
    edited May 2017

    Share here if you got any solution

  • JesperBaltzersenJesperBaltzersen DKUniversity ✭✭

    Nope, still no solution

  • leks_Kleks_K RUMember

    @Ajay_SBSIC @JesperChristensen @JesperBaltzersen @PedroConde have you found any solution for the reported issue?

  • JesperBaltzersenJesperBaltzersen DKUniversity ✭✭

    Nope, sorry:-(
    Still need it though, so please post if you have any success with it.

  • MuhammadHaggagMuhammadHaggag USMember ✭✭
    edited December 2017

    I managed to get this working.

    The key point is that you should not manipulate your own layouts or views when entering fullscreen, but show the given view directly. The WebView detaches the view that requested going fullscreen and passes it to you in OnShowCustomView, so if you manipulate your layouts (by hiding elements and maximizing the WebView), the element requesting fullscreen will show up as blank (since it's been detached).

    12-07 09:49:29.931 I/chromium(10040):  "requestFullscreen() is deprecated on insecure origins, and support will be removed in the future. You should consider switching your application to a secure origin, such as HTTPS.", source:  (0)
    12-07 09:49:29.943 E/eglCodecCommon(10040): glUtilsParamSize: unknow param 0x000085b5
    12-07 09:49:29.952 D/EGL_emulation(10040): eglMakeCurrent: 0x97b0c960: ver 3 1 (tinfo 0x97d2c890)
    12-07 09:49:29.963 E/eglCodecCommon(10040): glUtilsParamSize: unknow param 0x000085b5
    12-07 09:49:29.965 W/AwContents(10040): onDetachedFromWindow called when already detached. Ignoring
    12-07 09:49:30.053 D/Mono    (10040): Assembly Ref addref Mono.Android -> System.Runtime.Serialization: 4
    12-07 09:49:37.901 D/FullscreenEnabledWebViewRenderer(10040): Fullscreen requested with a view of type FrameLayout
    12-07 09:49:43.878 D/FullscreenEnabledWebViewRenderer(10040): Command for entering fullscreen is executable. Executing
    

    The hint was onDetachedFromWindow being called on AwContents. The View my FullscreenEnabledWebViewRenderer received was a FrameLayout presumably wrapping the WebView, or perhaps inside it. In any case, my renderer executes a command on my custom web view as follows:

            private void OnEnterFullscreenRequested(object sender, EnterFullscreenRequestedEventArgs e)
            {
                Log.Debug(Tag, $"Fullscreen requested with a view of type {e.View.GetType().Name}");
                if (_webView?.EnterFullscreenCommand == null)
                {
                    Log.Debug(Tag, "No command registered for entering fullscreen");
                    return;
                }
    
                var formsView = e.View.ToView();
                if (_webView.EnterFullscreenCommand.CanExecute(formsView))
                {
                    Log.Debug(Tag, "Command for entering fullscreen is executable. Executing");
                    _webView.EnterFullscreenCommand.Execute(formsView);
                }
                else
                {
                    Log.Debug(Tag, "Command for entering fullscreen is not executable. Skipping");
                }
            }
    

    The key point here is converting the native view to a Xamarin Forms view using the extension method LayoutExtensions.ToView. I pass this to the command, which executes the following method:

            private async Task EnterFullscreen(View view)
            {
                var page = new ContentPage() { Content = view };
                await _navigationService.PushModalAsync(page);
            }
    

    _navigationService is a custom navigation manager that just calls Navigation.PushModalAsync on the current page in this case.

  • leks_Kleks_K RUMember

    @MuhammadHaggag Hello. Can you throw off the source of some kind of example?

  • JesperBaltzersenJesperBaltzersen DKUniversity ✭✭

    @MuhammadHaggag Thanks for answering, looking forward to implementing it at some point. Like @leks_K I would also really appreciate source/example. Hope you are able to share.

  • MuhammadHaggagMuhammadHaggag USMember ✭✭

    I'll try to share a small example in the next couple of days.

  • MuhammadHaggagMuhammadHaggag USMember ✭✭
    Accepted Answer

    I apologize for the delay. Life happened :)

    I created a github repository with a sample implementation here:
    github.com/mhaggag/XFAndroidFullScreenWebView
    (The forum software won't allow me to post links from a new account, sorry)

  • JesperBaltzersenJesperBaltzersen DKUniversity ✭✭

    @MuhammadHaggag, I'm having trouble compiling it, but looks very promising.
    Thank you so much. What a pro way to answer a code sample request:-)

  • leks_Kleks_K RUMember

    @MuhammadHaggag, thanks, I will look and try to build in my prokect

  • ossentooossentoo GBMember ✭✭

    @MuhammadHaggag great solution. Used it to implement exactly what we needed.

    thanks

Sign In or Register to comment.