0
votes

So I have a WebView in my Xamarin Forms application, but I want to make changes to my iOS WebView by creating a custom renderer like recommended here: https://forums.xamarin.com/discussion/129626/how-does-one-implement-wkwebview-ios-in-a-cross-platform-application

I'm not sure how to alter my XAML file though, to call my custom renderer for iOS, and the normal WebView for Android. Currently my XAML file looks like this:

<WebView Source="{Binding StartUrl}"
               Navigated="OnBrowserNavigated"
               Navigating="OnBrowserNavigating"
               AbsoluteLayout.LayoutFlags="All"
               AbsoluteLayout.LayoutBounds="0.5, 0.5, 1, 1"/>

Which is using the keyword WebView (Xamarin.Forms.WebView). But if I create a custom renderer for iOS using this method:

// Create a new class:
public class MyWebView : WebView
{
    public static readonly BindableProperty UrlProperty = BindableProperty.Create(...);
    ...
}

// Create custom renderer:
[assembly: ExportRenderer(typeof(MyWebView), typeof(MyWebViewRenderer))]
namespace WKWebViewDemo.iOS
{
...    
}

How am I supposed to call this renderer like the page says to

<StackLayout>
    <local:MyWebView Url="https://www.microsoft.com" VerticalOptions="FillAndExpand"/>
</StackLayout>

AND still call the Xamarin.Forms.WebView for android like my XAML page is doing right now?

2
if there is not a custom renderer defined on Android it will just use the base rendererJason
Ok, so if I just use the "MyWebView" class, Xamarin will look for it in the android app but since it's not there it will just ignore it and use Xamarin.Forms.WebView?chung
it will look for a renderer. If there is not one for MyWebView, it will look for one of the base class, WebView.Jason
Ok, and so my android webview would use source=url, and the iOS would use Url=url like you see in the question, would I add both of them into my XAML layout?chung
No, that would be a problem. Both platforms need to have the same API surface. Why do you need a different url property than the one the base control has?Jason

2 Answers

1
votes

As the Url property is which you defined in your MyWebView ,if you delete the MyWebView class,it will throw not defined error.

if you want to use Source property both in Android and ios,you could not defined a custom webview,and use the WebView in the renderer directly in ios like :

// Create custom renderer:
[assembly: ExportRenderer(typeof(WebView), typeof(MyWebViewRenderer))]
namespace WKWebViewDemo.iOS
{
  public class MyWebViewRenderer : ViewRenderer<WebView, WKWebView>
  {
    WKWebView _wkWebView;
    protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
    {
        base.OnElementChanged(e);

        if (Control == null)
        {
            var config = new WKWebViewConfiguration();
            _wkWebView = new WKWebView(Frame, config);
            SetNativeControl(_wkWebView);
        }
        if (e.NewElement != null)
        {
            Control.LoadRequest(new NSUrlRequest(new NSUrl(((UrlWebViewSource)Element.Source).Url)));
        }
    }
  }
}
0
votes
<WebView Source="{Binding StartUrl}"
         Url="{Binding StartUrl}"
               ...>

So this actually did work, the iOS WebView worked well, but the way I want to remove the Url and use "Source" for both is this.

namespace Apm.Mobile.Core.Controls
{
public class BetterWebView : WebView
{
    public static readonly BindableProperty UrlProperty = BindableProperty.Create(
        propertyName: "Source", // This is now source instead of Url
        returnType: typeof(string),
        declaringType: typeof(BetterWebView),
        defaultValue: default(string));

    public new string Source // This string is now Source instead of Url
    {
        get { return (string)GetValue(UrlProperty); }
        set { SetValue(UrlProperty, value); }
    }
}
}