In Xamarin.Forms it is documented that on iOS you can use WkWebViewRenderer
instead of UIWebView
which will be deprecated in near future.
However when using WkWebViewRenderer
there is a serious problem that when tapping on links with target = _blank
nothing happens. And there is no possibility to handle that in Xamarin.Forms.
[assembly: ExportRenderer(typeof(WebView), typeof(WkWebViewRenderer))]
in AssemblyInfo.cs
in iOS project
Webview should redirect to Facebook page.
Nothing happens.
Any chance you should attach that simple reproduction? I'll re-create it if not, but when we get a bunch of bugs to go through not having to create reproductions really saves us a bunch of time! Thanks!
Here is the reproduction project:
App1.zip
Run it and click on Facebook logo:
As you will notice nothing happens
Hey @kingces95! Why have you labeled this "needs-repro"? It is fairly easy to reproduce that. I have even provided a project with reproduction.
Please remove also "unverified"
Pretty sure this can be worked around using a custom renderer, subclassing WkWebViewRenderer
, and overriding the DecidePolicy
method to check the navigationAction
parameter for the target and either opening the URL in the same window or an external one. (Some references here and here).
But that's kind of a pain for users. We should see if we have a similar issue on the other platforms (how they handle target=_blank) - it may make sense to add a property on WebView for blank target handling policy. Or, if iOS is the only place we have this issue, we should make it behave consistently with the other platforms, and provide some guidance on overriding that behavior.
Another option (if iOS is the only platform with this issue) would be to add something like BlankTargetHandlingPolicy
as a Platform Specific for iOS.
Pretty sure this can be worked around using a custom renderer, subclassing
WkWebViewRenderer
, and overriding theDecidePolicy
method to check thenavigationAction
parameter for the target and either opening the URL in the same window or an external one. (Some references here and here).But that's kind of a pain for users. We should see if we have a similar issue on the other platforms (how they handle target=_blank) - it may make sense to add a property on WebView for blank target handling policy. Or, if iOS is the only place we have this issue, we should make it behave consistently with the other platforms, and provide some guidance on overriding that behavior.
Another option (if iOS is the only platform with this issue) would be to add something like
BlankTargetHandlingPolicy
as a Platform Specific for iOS.
Could you provide an example code of this custom renderer?
@Mikilll94 First, create your own WebView inheritance in your shared project like this
using System;
using Xamarin.Forms;
namespace App1
{
public class MyWebView : WebView
{
}
}
Consume it, again in your shared project, like this:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:app1="clr-namespace:App1"
mc:Ignorable="d"
x:Class="App1.MainPage">
<app1:MyWebView Source="https://sollers.eu"/>
</ContentPage>
Then, in your iOS project, create a custom renderer like this
using System;
using App1;
using App1.iOS;
using Foundation;
using WebKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(MyWebView), typeof(MyWebViewRenderer))]
namespace App1.iOS
{
public class MyWebViewRenderer : WkWebViewRenderer, IWKNavigationDelegate
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
NavigationDelegate = this;
}
[Export("webView:decidePolicyForNavigationAction:decisionHandler:")]
public void DecidePolicy(WKWebView webView, WKNavigationAction navigationAction, Action<WKNavigationActionPolicy> decisionHandler)
{
if (navigationAction.TargetFrame == null)
{
webView.LoadRequest(navigationAction.Request);
}
decisionHandler.Invoke(WKNavigationActionPolicy.Allow);
}
}
}
Effectively what this does is check if the link that is clicked has target = "_blank"
and if so, it resends the requests but now in the same screen.
Your adapted reproduction is here:
App1_withRenderer.zip
@jfversluis Thanks, a lot :)
@jfversluis
Your solution works, but Navigating and Navigated events are not called. Maybe do you have a solution for that?
Ugh, yeah, OK that sucks. The only quick way I see is to basically take this whole delegate from the actual renderer and add the piece from my renderer in the project I added.
Since our delegate is private you can't create an inheritance from that
@jfversluis
Could you have some example implementation? Because I was trying to copy this navigation delegate and unfortunately this is not so easy to implement.
@Mikilll94 Again, this sucks. I've been trying to look into it to make a workaround for now, but you need to pull in a lot of code from the repo to make this work because a lot of the methods and fields you need are private or internal.
Therefore I just decided to implement the fix and make a PR. That will mean that hopefully it is added soon, but I don't have a decent workaround for you right now. If this is something that is important to you, you might want to stick to the UIWebView
for now until this fix is incorporated.
@jfversluis
Thanks for your response :)
closed by #8281
@jfversluis
Your solution works, but Navigating and Navigated events are not called. Maybe do you have a solution for that?
This worked for me:
```
[assembly:ExportRenderer (typeof(MyCustomWebview), typeof(MyCustomWebviewRendererIOS))]
namespace XYZ.iOS
{
public class MyCustomWebviewRendererIOS: WkWebViewRenderer, IWKNavigationDelegate
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (NativeView != null)
{
WeakUIDelegate = this;
}
}
[Export("webView:createWebViewWithConfiguration:forNavigationAction:windowFeatures:")]
public WKWebView CreateWebView(WKWebView webView, WKWebViewConfiguration configuration, WKNavigationAction action, WKWindowFeatures features)
{
if (action.Request.Url != null)
{
webView.LoadRequest(new NSUrlRequest(action.Request.Url));
}
return null;
}
}
}
Has this bug fix been released yet? I'm still seeing the issue where links with Target="_blank" are being ignored.
@dpuckett Yes, this fix has been released. If you're still seeing this issue on the latest version of Forms, please open a new issue and we'll take a look.
Most helpful comment
@Mikilll94 First, create your own WebView inheritance in your shared project like this
Consume it, again in your shared project, like this:
Then, in your iOS project, create a custom renderer like this
Effectively what this does is check if the link that is clicked has
target = "_blank"
and if so, it resends the requests but now in the same screen.Your adapted reproduction is here:
App1_withRenderer.zip