如果 "target=_blank",Xamarin Android WebView 不会触发导航
Xamarin Android WebView don't fire navigating if "target=_blank"
我在 xamarin 中使用 webview,我按照许多教程来处理导航,并且一切正常。
我的问题是:当锚标记具有 target="_blank" 时,永远不会触发事件 Navigating。
我看到周围有人给出了一个 javascript 解决方案,该解决方案删除了 target=_blank 并将其附加在 href link.
的末尾
这样做真的是正确的方法吗?看起来有线..
谢谢
这是 xamarin.android 渲染器中的初始化
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
global::Android.Webkit.WebView.SetWebContentsDebuggingEnabled(true);
if (e.OldElement != null)
{
Control.RemoveJavascriptInterface("jsBridge");
((HybridWebView)Element).Cleanup();
}
if (e.NewElement != null)
{
Control.Settings.JavaScriptEnabled = true;
Control.Settings.DomStorageEnabled = true;
Control.Settings.JavaScriptCanOpenWindowsAutomatically = true;
Control.Settings.SetSupportMultipleWindows(true);
Control.Settings.AllowFileAccessFromFileURLs = true;
Control.Settings.AllowUniversalAccessFromFileURLs = true;
Control.Settings.UserAgentString = Control.Settings.UserAgentString + " crmvw";
Android.Webkit.WebChromeClient xCC = new CustChromeWebViewClient(_context);
Control.SetWebChromeClient(xCC);
Control.SetWebViewClient(new CrmWebViewClient(this, $"javascript: {JavascriptFunction}"));
Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
Control.LoadUrl(((HybridWebView)Element).Uri);
}
}
这是我的导航事件,当锚点有 target=_blank 时从未触发
private void webv_Navigating(object sender, WebNavigatingEventArgs e)
{
if (IsFirstLoad) {
IsBusy = true;
IsFirstLoad = false;
}
if (e.Url.ToLower().StartsWith("tel:") || e.Url.ToString().StartsWith("wtai:") || e.Url.ToLower().StartsWith("sms:") || e.Url.ToLower().StartsWith("mailto:"))
{
e.Cancel = true;
}
}
这里是我自定义 WEBView
中 URL 的覆盖函数
public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, Android.Webkit.IWebResourceRequest request)
{
Android.Net.Uri url = request.Url;
if (url.ToString().StartsWith("tel:") || url.ToString().StartsWith("wtai:"))
{
Xamarin.Essentials.PhoneDialer.Open(UtilityXam.Contact.GetPhoneFromHTML(url.ToString()));
return true;
}else if (url.ToString().StartsWith("mailto:"))
{
UtilityXam.Contact xE = new UtilityXam.Contact();
string xEmail = UtilityXam.Contact.GetEmailFromHTML( url.ToString());
var xTask = xE.SendEmail("","",new System.Collections.Generic.List<string>(){ xEmail });
return true;
}
else if (url.ToString().StartsWith("sms:"))
{
UtilityXam.Contact xE = new UtilityXam.Contact();
string xPh = UtilityXam.Contact.GetPhoneFromHTML(url.ToString());
var xTask = xE.SendSMS("", "", new System.Collections.Generic.List<string>() { xPh });
}
else
{
view.LoadUrl(url.ToString());
}
view.SetDownloadListener(new CrmDownloadListener(_context));
return true;
}
在Jack Hua的大力帮助下,我得以解决问题。
在混合渲染器的 OnElementChanged 中,我设置了对多个 windows.
的支持
Control.Settings.SetSupportMultipleWindows(true);
接下来我必须在自定义 chrome webview 中管理 onCreateWindow 事件。
这里的代码从 Jack 建议的 link 转换为 c#。
public override bool OnCreateWindow(Android.Webkit.WebView view, bool isDialog, bool isUserGesture, Android.OS.Message resultMsg)
{
Android.Webkit.WebView newWebView = new Android.Webkit.WebView(_context);
view.AddView(newWebView);
Android.Webkit.WebView.WebViewTransport transport = (Android.Webkit.WebView.WebViewTransport) resultMsg.Obj;
transport.WebView = newWebView;
resultMsg.SendToTarget();
return true;
}
这是 Xamarin Forms 自 v4.8.0.1364 以来引入的错误(至少根据错误报告)
您现在可以通过从 url 中删除 target="_blank"
或设置 属性
来解决这个问题
webView.Settings.SetSupportMultipleWindows(true);
我已经为我们的应用程序修复了它,方法是在一些已经在内容上运行的替换逻辑中剥离 target="_blank"
和 target='_blank'
Xamarin Forms 有多个未解决的问题报告 github
[Bug] Cannot open URLs with WebView android when the target is _blank #12917
[Bug] Android WebView's Navigating and Navigated events not fired #12852
我尝试了一种完全不同的方法,因为上面的答案并没有真正帮助(我的目标 _blank 链接总是在新的 chrome 实例中打开,而不是在应用程序内浏览器中打开)。
首先,您需要将 SetSupportMultipleWindows 设置为 false。一旦您这样做,所有 windows 将在同一个 webView 中打开:
Control.Settings.SetSupportMultipleWindows(false);
有关如何设置这些设置的更多信息:https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/hybridwebview
接下来,我所做的就是更改后退按钮的行为,以确保后退按钮不会关闭应用程序,而是导航 webview 页面(HybridWebView 是我在第一步中创建的自定义 webview) .
HybridWebView _browser;
public MainPage()
{
_browser = new HybridWebView
{
Source = "https://brandschutzplaner-stahltragwerke.promat.ch"
};
Content = _browser;
}
protected override bool OnBackButtonPressed()
{
base.OnBackButtonPressed();
if (_browser.CanGoBack)
{
_browser.GoBack();
return true;
}
else
{
base.OnBackButtonPressed();
return true;
}
}
我在 xamarin 中使用 webview,我按照许多教程来处理导航,并且一切正常。 我的问题是:当锚标记具有 target="_blank" 时,永远不会触发事件 Navigating。
我看到周围有人给出了一个 javascript 解决方案,该解决方案删除了 target=_blank 并将其附加在 href link.
的末尾这样做真的是正确的方法吗?看起来有线..
谢谢
这是 xamarin.android 渲染器中的初始化
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
global::Android.Webkit.WebView.SetWebContentsDebuggingEnabled(true);
if (e.OldElement != null)
{
Control.RemoveJavascriptInterface("jsBridge");
((HybridWebView)Element).Cleanup();
}
if (e.NewElement != null)
{
Control.Settings.JavaScriptEnabled = true;
Control.Settings.DomStorageEnabled = true;
Control.Settings.JavaScriptCanOpenWindowsAutomatically = true;
Control.Settings.SetSupportMultipleWindows(true);
Control.Settings.AllowFileAccessFromFileURLs = true;
Control.Settings.AllowUniversalAccessFromFileURLs = true;
Control.Settings.UserAgentString = Control.Settings.UserAgentString + " crmvw";
Android.Webkit.WebChromeClient xCC = new CustChromeWebViewClient(_context);
Control.SetWebChromeClient(xCC);
Control.SetWebViewClient(new CrmWebViewClient(this, $"javascript: {JavascriptFunction}"));
Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
Control.LoadUrl(((HybridWebView)Element).Uri);
}
}
这是我的导航事件,当锚点有 target=_blank 时从未触发
private void webv_Navigating(object sender, WebNavigatingEventArgs e)
{
if (IsFirstLoad) {
IsBusy = true;
IsFirstLoad = false;
}
if (e.Url.ToLower().StartsWith("tel:") || e.Url.ToString().StartsWith("wtai:") || e.Url.ToLower().StartsWith("sms:") || e.Url.ToLower().StartsWith("mailto:"))
{
e.Cancel = true;
}
}
这里是我自定义 WEBView
中 URL 的覆盖函数 public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, Android.Webkit.IWebResourceRequest request)
{
Android.Net.Uri url = request.Url;
if (url.ToString().StartsWith("tel:") || url.ToString().StartsWith("wtai:"))
{
Xamarin.Essentials.PhoneDialer.Open(UtilityXam.Contact.GetPhoneFromHTML(url.ToString()));
return true;
}else if (url.ToString().StartsWith("mailto:"))
{
UtilityXam.Contact xE = new UtilityXam.Contact();
string xEmail = UtilityXam.Contact.GetEmailFromHTML( url.ToString());
var xTask = xE.SendEmail("","",new System.Collections.Generic.List<string>(){ xEmail });
return true;
}
else if (url.ToString().StartsWith("sms:"))
{
UtilityXam.Contact xE = new UtilityXam.Contact();
string xPh = UtilityXam.Contact.GetPhoneFromHTML(url.ToString());
var xTask = xE.SendSMS("", "", new System.Collections.Generic.List<string>() { xPh });
}
else
{
view.LoadUrl(url.ToString());
}
view.SetDownloadListener(new CrmDownloadListener(_context));
return true;
}
在Jack Hua的大力帮助下,我得以解决问题。 在混合渲染器的 OnElementChanged 中,我设置了对多个 windows.
的支持Control.Settings.SetSupportMultipleWindows(true);
接下来我必须在自定义 chrome webview 中管理 onCreateWindow 事件。 这里的代码从 Jack 建议的 link 转换为 c#。
public override bool OnCreateWindow(Android.Webkit.WebView view, bool isDialog, bool isUserGesture, Android.OS.Message resultMsg)
{
Android.Webkit.WebView newWebView = new Android.Webkit.WebView(_context);
view.AddView(newWebView);
Android.Webkit.WebView.WebViewTransport transport = (Android.Webkit.WebView.WebViewTransport) resultMsg.Obj;
transport.WebView = newWebView;
resultMsg.SendToTarget();
return true;
}
这是 Xamarin Forms 自 v4.8.0.1364 以来引入的错误(至少根据错误报告)
您现在可以通过从 url 中删除 target="_blank"
或设置 属性
webView.Settings.SetSupportMultipleWindows(true);
我已经为我们的应用程序修复了它,方法是在一些已经在内容上运行的替换逻辑中剥离 target="_blank"
和 target='_blank'
Xamarin Forms 有多个未解决的问题报告 github
[Bug] Cannot open URLs with WebView android when the target is _blank #12917
[Bug] Android WebView's Navigating and Navigated events not fired #12852
我尝试了一种完全不同的方法,因为上面的答案并没有真正帮助(我的目标 _blank 链接总是在新的 chrome 实例中打开,而不是在应用程序内浏览器中打开)。
首先,您需要将 SetSupportMultipleWindows 设置为 false。一旦您这样做,所有 windows 将在同一个 webView 中打开:
Control.Settings.SetSupportMultipleWindows(false);
有关如何设置这些设置的更多信息:https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/hybridwebview
接下来,我所做的就是更改后退按钮的行为,以确保后退按钮不会关闭应用程序,而是导航 webview 页面(HybridWebView 是我在第一步中创建的自定义 webview) .
HybridWebView _browser;
public MainPage()
{
_browser = new HybridWebView
{
Source = "https://brandschutzplaner-stahltragwerke.promat.ch"
};
Content = _browser;
}
protected override bool OnBackButtonPressed()
{
base.OnBackButtonPressed();
if (_browser.CanGoBack)
{
_browser.GoBack();
return true;
}
else
{
base.OnBackButtonPressed();
return true;
}
}