假设您要阻止用户从您的Xamarin.Forms.WebView导航到外部页面。
public App ()
{
var webView = new WebView
{
Source = new HtmlWebViewSource
{
Html = "<h1>Hello world</h1><a href='http://example.com'>Can't escape!</a><iframe width='420' height='315' src='https://www.youtube.com/embed/oHg5SJYRHA0' frameborder='0' allowfullscreen></iframe>"
}
};
webView.Navigating += WebView_Navigating;
MainPage = new ContentPage {
Content = webView
};
}
private void WebView_Navigating(object sender, WebNavigatingEventArgs e)
{
// we don't want to navigate away from our page
// open it in a new page instead etc.
e.Cancel = true;
}
这适用于Windows和Android。但是在iOS上,根本没有加载!
在iOS上,即使从HtmlWebViewSource加载源代码时,也会引发Navigating事件,其URL看起来像file:///Users/[user]/Library/Developer/CoreSimulator/Devices/[deviceID]/data/Containers/Bundle/Application/[appID]/[appName].app/
好吧,所以你可以用这样的东西来解决这个问题:
private void WebView_Navigating(object sender, WebNavigatingEventArgs e)
{
if (e.Url.StartsWith("file:") == false)
e.Cancel = true;
}
该页面最终在iOS上加载。好极了。可是等等!嵌入的YouTube视频无法加载!那是因为导航事件会引发嵌入式资源的内部导航,例如iframe甚至外部脚本(如Twitter的<script charset="utf-8" type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>
),但仅限于iOS!
我找不到确定Navigating事件是从内部导航引发还是因为用户点击链接的方法。
如何解决这个问题?
答案 0 :(得分:5)
我不确定是否可以在开箱即用的Xamarin Forms中进行检测,但使用自定义渲染器可以轻松确定导航类型。在自定义iOS渲染器中,分配WebViewDelegate并在该Delegate类中,覆盖ShouldStartLoad()
,如下所示:
public class CustomWebViewRenderer : WebViewRenderer {
#region Properties
public CustomWebView CustomWebViewItem { get { return Element as CustomWebView; } }
#endregion
protected override void OnElementChanged(VisualElementChangedEventArgs e) {
base.OnElementChanged(e);
if(e.OldElement == null) {
Delegate = new CustomWebViewDelegate(); //Assigning the delegate
}
}
}
internal class CustomWebViewDelegate : UIWebViewDelegate {
public override bool ShouldStartLoad(UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navigationType) {
if(navigationType == UIWebViewNavigationType.LinkClicked) {
//To prevent navigation when a link is click, return false
return false;
}
return true;
}
}
您还可以将bool属性或甚至枚举备份到您的Xamarin表单WebView
,这可以说明Navigating
事件是来自被点击的链接还是其他内容,尽管是自定义的也需要渲染器。
答案 1 :(得分:2)
private bool isNavigated = false;
public CustomWebView()
{
if (Device.OS == TargetPlatform.Android)
{
// always true for android
isNavigated = true;
}
Navigated += (sender, e) =>
{
isNavigated = true;
};
Navigating += (sender, e) =>
{
if (isNavigated)
{
try
{
var uri = new Uri(e.Url);
Device.OpenUri(uri);
}
catch (Exception)
{
}
e.Cancel = true;
}
};
}