HTML mixed with XForms Help!

joellinderjoellinder SEMember ✭✭

Hi, i am developing an app and i am trying to load an html page with a HybridWebView("https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/custom-renderer/hybridwebview/").

On the html page im trying to load i have a bootstrap Carousel control(https://v4-alpha.getbootstrap.com/components/carousel/#via-data-attributes). The problem is that its not visible! All other elements are visible except the Carousel. If i load the html page up on my android phones in chrome it works perfectly. Why is it not working in xamarin? Does not xamarin support JQuery?

My HTML


    <style>
        .carousel-inner {
            height: 100%;
            background-size: cover;
            background-position: center;
            background-repeat: no-repeat;
        }
    </style>
</head>
<body>

    <h3>Hello World</h3>
    <h3>Sup!</h3>

    <div id="carouselExampleIndicators" class="carousel slide" data-ride="carousel" style="background-color: aqua">
        <ol class="carousel-indicators">
            <li data-target="#carouselExampleIndicators" data-slide-to="0" class="active"></li>
            <li data-target="#carouselExampleIndicators" data-slide-to="1"></li>
            <li data-target="#carouselExampleIndicators" data-slide-to="2"></li>
        </ol>
        <div class="carousel-inner" role="listbox">
            <div class="carousel-item active">
                <h1>First Slide</h1>
            </div>
            <div class="carousel-item">
                <h1>Second Slide</h1>
            </div>
            <div class="carousel-item">
                <h1>Third Slide</h1>
            </div>
        </div>
        <a class="carousel-control-prev" href="#carouselExampleIndicators" role="button" data-slide="prev">
            <span class="carousel-control-prev-icon" aria-hidden="true"></span>
            <span class="sr-only">Previous</span>
        </a>
        <a class="carousel-control-next" href="#carouselExampleIndicators" role="button" data-slide="next">
            <span class="carousel-control-next-icon" aria-hidden="true"></span>
            <span class="sr-only">Next</span>
        </a>
    </div>


    <script src="https://code.jquery.com/jquery-3.2.1.min.js"
            integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
            crossorigin="anonymous"></script>
    <script src="https://code.jquery.com/jquery-migrate-3.0.0.min.js"
            integrity="sha256-JklDYODbg0X+8sPiKkcFURb5z7RvlNMIaE3RA2z97vw="
            crossorigin="anonymous"></script>


    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>

    <script type="text/javascript">

        var $item = $('.carousel .item');
        var $wHeight = $(window).height();
        $item.eq(0).addClass('active');
        $item.height($wHeight);
        $item.addClass('full-screen');

        $('.carousel img').each(function () {
            var $src = $(this).attr('src');
            var $color = $(this).attr('data-color');
            $(this).parent().css({
                'background-image': 'url(' + $src + ')',
                'background-color': $color
            });
            $(this).remove();
        });

        $(window).on('resize', function () {
            $wHeight = $(window).height();
            $item.height($wHeight);
        });


        $('.carousel').carousel()

        function log(str)
        {
            $('#result').text($('#result').text() + " " + str);
        }

        function invokeCSCode(data) {
            try {
                log("Sending Data:" + data);
                invokeCSharpAction(data);
            }
            catch (err){
                log(err);
            }
        }
    </script>
</body>
</html>

My HybridWebView Android Implementation

public class HybridWebViewRenderer : ViewRenderer<HybridWebView, Android.Webkit.WebView>
    {
        const string JavaScriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";

        protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
        {
            base.OnElementChanged(e);

            if(Control == null)
            {
                var webView = new Android.Webkit.WebView(Forms.Context);
                webView.Settings.JavaScriptEnabled = true;
                webView.Settings.AllowFileAccess = true;
                webView.Settings.AllowFileAccessFromFileURLs = true;
                webView.Settings.AllowContentAccess = true;
                webView.SetWebChromeClient(new WebChromeClient());
                SetNativeControl(webView);
            }
            if(e.OldElement != null)
            {
                Control.RemoveJavascriptInterface("jsBridge");
                var hybridWebView = e.OldElement as HybridWebView;
                hybridWebView.Cleanup();
            }
            if(e.NewElement != null)
            {
                Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
                Control.LoadUrl(string.Format("file:///android_asset/Content/{0}", Element.Uri));
                InjectJS(JavaScriptFunction);
            }
        }

        void InjectJS(string script)
        {
            if (Control != null)
            {
                Control.LoadUrl(string.Format("javascript: {0}", script));
            }
        }
    }

Best Answer

  • joellinderjoellinder SEMember ✭✭
    Accepted Answer

    I was able to solve this myself.
    I tested to rewrite it to a ordinary android application and noticed that it only worked when the WebView element was the top node like this:

    <?xml version="1.0" encoding="utf-8"?>
    <WebView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/webview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
    

    I figured xamarin forms does not place viewrender elements automatically at the top of the hierarchy.
    So i checked xamarin`s own webview implementation online and found that by adding this line of code "webView.LayoutParameters = new global::Android.Widget.AbsoluteLayout.LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent, 0, 0);" to the webView object solves the problem. Also sorry for my mediocre English.

    if (Control == null)
                {
                    var webView = CreateNativeControl();
    #pragma warning disable 618 // This can probably be replaced with LinearLayout(LayoutParams.MatchParent, LayoutParams.MatchParent); just need to test that theory
                    webView.LayoutParameters = new global::Android.Widget.AbsoluteLayout.LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent, 0, 0);
    #pragma warning restore 618
                    webView.SetWebViewClient(new WebClient(this));
    
                    _webChromeClient = GetFormsWebChromeClient();
                    _webChromeClient.SetContext(Context as IStartActivityForResult);
                    webView.SetWebChromeClient(_webChromeClient);
    
                    webView.Settings.JavaScriptEnabled = true;
                    webView.Settings.DomStorageEnabled = true;
                    SetNativeControl(webView);
                }
    

Answers

  • joellinderjoellinder SEMember ✭✭
    Accepted Answer

    I was able to solve this myself.
    I tested to rewrite it to a ordinary android application and noticed that it only worked when the WebView element was the top node like this:

    <?xml version="1.0" encoding="utf-8"?>
    <WebView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/webview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
    

    I figured xamarin forms does not place viewrender elements automatically at the top of the hierarchy.
    So i checked xamarin`s own webview implementation online and found that by adding this line of code "webView.LayoutParameters = new global::Android.Widget.AbsoluteLayout.LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent, 0, 0);" to the webView object solves the problem. Also sorry for my mediocre English.

    if (Control == null)
                {
                    var webView = CreateNativeControl();
    #pragma warning disable 618 // This can probably be replaced with LinearLayout(LayoutParams.MatchParent, LayoutParams.MatchParent); just need to test that theory
                    webView.LayoutParameters = new global::Android.Widget.AbsoluteLayout.LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent, 0, 0);
    #pragma warning restore 618
                    webView.SetWebViewClient(new WebClient(this));
    
                    _webChromeClient = GetFormsWebChromeClient();
                    _webChromeClient.SetContext(Context as IStartActivityForResult);
                    webView.SetWebChromeClient(_webChromeClient);
    
                    webView.Settings.JavaScriptEnabled = true;
                    webView.Settings.DomStorageEnabled = true;
                    SetNativeControl(webView);
                }
    
Sign In or Register to comment.