我有一个 Xamarin 应用程序,正在尝试移植到 MAUI。它有一个显示远程 HTML 内容的 WebView 控件。还有一个 ActivityIndicator 用于指示何时进行导航。在 Android 上,WebView 的 Navigating 事件在页面开始加载时触发,而 Navigated 事件在 WebView 完成页面加载时触发,正如预期的那样。 ActivityIndicator 显示在导航事件处理程序中,并隐藏在导航事件处理程序中。然而,在 iOS 上,导航事件可以在页面加载期间多次触发,与导航事件相同。问题是,导航事件并不总是在最后一个导航事件之后触发。这通常会使活动指示器在导航到新页面完成后可见。
在 Xamarin 中,我通过使用 iOS 的自定义渲染器解决了这个问题,如下所示。我知道 MAUI 处理程序应该取代 Xamarin 自定义渲染器,但我找到的所有示例都没有显示如何映射到 iOS 本机 Web 视图控件中的事件,正如我所做的那样。有谁知道如何做到这一点或者是否有更好的方法来解决这个问题?
跨平台层:
using Xamarin.Forms;
namespace MyXamarinApp.CustomControls
{
public class CustomWebView : WebView
{
public delegate void NavigateDel(bool flag);
public event NavigateDel NavigateEvent;
public void CallNavigate(bool flag)
{
NavigateEvent(flag);
}
}
}
iOS层:
using MyXamarinApp.CustomControls;
using MyXamarinApp.iOS.Renderers;
using Foundation;
using WebKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(WebView), typeof(CustomWebViewRenderer))]
namespace MyXamarinApp.iOS.Renderers
{
class MyDelegate : WKNavigationDelegate
{
readonly CustomWebView customView;
public MyDelegate(CustomWebView view)
{
customView = view;
}
public override void DidStartProvisionalNavigation(WKWebView webView, WKNavigation navigation)
{
customView.CallNavigate(true);
}
public override void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
{
customView.CallNavigate(false);
}
public override void DidFailNavigation(WKWebView webView, WKNavigation navigation, NSError error)
{
customView.CallNavigate(false);
}
}
class CustomWebViewRenderer : WkWebViewRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
CustomWebView control = (CustomWebView)Element;
this.NavigationDelegate = new MyDelegate(control);
}
}
}
}
WebView 有
Navigated
事件,该事件在页面导航完成时引发。在 Navigated
事件中,我们可以访问指示导航结果的 WebNavigedEventArgs 对象。
假设我们有一个
WebView
和 ActivityIndicator
。我在这里使用 Navigated
事件,
<WebView x:Name="CustomWebView" WidthRequest="300" HeightRequest="300" Source="https://learn.microsoft.com/dotnet/maui"
Navigated="CustomWebView_Navigated" />
<ActivityIndicator x:Name="myIndicator" IsRunning="true" />
所以,在后面的代码中,让我们实现这个事件处理程序,
void CustomWebView_Navigated(System.Object sender, Microsoft.Maui.Controls.WebNavigatedEventArgs e)
{
switch (e.Result)
{
case WebNavigationResult.Cancel:
// do something
break;
case WebNavigationResult.Failure:
// do something
break;
case WebNavigationResult.Success:
// do something
myIndicator.IsRunning = false;
break;
case WebNavigationResult.Timeout:
// do something
break;
default:
// do something
break;
}
}
我们可以根据
WebNavigationResult
来实现我们的逻辑。这里当WebNavigationResult
成功时,我通过设置ActivityIndicator
来隐藏IsRunning = false
。
希望有帮助!