Tracking down WebView URL’s Changes in Xamarin Forms

Hi guys, in this post I just want to share a simple tip that maybe you guys gonna need it. So, in my latest project, I created an app that had a webview on it. Among those web pages that I need to show, there was a certain page that I couldn’t display to the user because it didn’t work properly. In order to keep the business process run well, I had to navigate back to native page whenever user reach that page. In short, I need put a tracker on my webview. I look up to the internet but couldn’t find anything that suit my need so I came up with simple solution.

Custom WebView

The Original Xamarin Forms’s Webview of course didn’t support this tracking feature, even tough you bind a certain variable to source property of web view, it won’t change when you navigate to to other pages. So, we gonna need new property, I call it CurrentUrl.

public class CustomWebView : WebView
{
    public static BindableProperty CurrentUrlProperty =
        BindableProperty.Create(nameof(CurrentUrl), typeof(string), typeof(CustomWebView), null, BindingMode.TwoWay);

    public string CurrentUrl
    {
        get { return (string)GetValue(CurrentUrlProperty); }
        set { SetValue(CurrentUrlProperty, value); }
    }
}

I gonna use this new property to store the current url the web view is showing. No, let see how to store that current url.

WebView Delegate

Because my project requirement only for iOS, for now I just gonna show you how to do it in iOS. But I guess it won’t be much different in Android side.

So, I store the current URL on method ShouldStartLoad in UIWebViewDelegate. That method is run whenever you’re loading¬† a new page. This is also the method where you put header to web page, if it’s needed.¬† This is how the renderer and delegate look like.

public class CustomWebViewRenderer : WebViewRenderer
{
    protected override void OnElementChanged(VisualElementChangedEventArgs e)
    {
        base.OnElementChanged(e);
        Delegate = new CustomUiWebViewDelegate(this);
    }
}

public class CustomUiWebViewDelegate : UIWebViewDelegate
{
CustomWebViewRenderer customWebViewRenderer;
    public CustomUiWebViewDelegate(CustomWebViewRenderer _webViewRenderer = null)
    {
        customWebViewRenderer = _webViewRenderer ?? new CustomWebViewRenderer();
    }

    public override bool ShouldStartLoad(UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navigationType)
    {
       var wv = customWebViewRenderer.Element as CustomWebView;
       wv.CurrentUrl = request.Url.ToString();
       return true;
    }
}

View Model

The last thing you need to do is binding that CurrentUrl property to certain variable in view model. So, whenever it changes, you can trigger something to be done. In the example below, I bind it to a variable with the same name, CurrentUrl.

public class WebViewViewModel : BaseViewModel
{
    private string currentUrl;
    public string CurrentUrl
    {
        get => currentUrl;
        set
        {
            SetProperty(ref currentUrl, value);
DoSomething(value);
        }
    }

    public WebViewViewModel()
    { }

    private void DoSomething(string url)
    {
        // actually do something here<span id="mce_SELREST_start" style="overflow:hidden;line-height:0;">&#65279;</span>
    }
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s