Xamarin.Forms通过JavascriptWebViewClient的ShouldOverrideUrlLoading触发ActivityIndicator
Xamarin.Forms 原生WebViewClient控制共享层加载指示器实现方案
核心实现逻辑:在自定义HybridWebView中新增加载状态事件,原生端Web生命周期回调触发事件,共享层订阅事件控制指示器状态,具体修改如下:
1. 修改共享项目 HybridWebView 类
新增加载状态事件与触发方法,确保回调在UI线程执行:
public class HybridWebView : WebView { private Action<string, string> _action; // 新增加载状态事件 public event EventHandler PageLoading; public event EventHandler PageLoaded; public void RegisterAction(Action<string, string> callback) { _action = callback; } public void Cleanup() { _action = null; } public void InvokeAction(string param1, string param2) { if (_action == null || (param1 == null && param2 == null)) { return; } if (MainThread.IsMainThread) _action.Invoke(param1, param2); else MainThread.BeginInvokeOnMainThread(() => _action.Invoke(param1, param2)); } // 新增触发加载开始事件的方法 public void OnPageLoading() { MainThread.BeginInvokeOnMainThread(() => PageLoading?.Invoke(this, EventArgs.Empty)); } // 新增触发加载结束事件的方法 public void OnPageLoaded() { MainThread.BeginInvokeOnMainThread(() => PageLoaded?.Invoke(this, EventArgs.Empty)); } }
2. 修改Android端 JavascriptWebViewClient 类
构造方法接收HybridWebView实例,在Web生命周期回调中触发加载事件:
public class JavascriptWebViewClient : WebViewClient { readonly string _javascript; readonly HybridWebView _hybridWebView; // 构造方法新增HybridWebView参数 public JavascriptWebViewClient(string javascript, HybridWebView webView) { _javascript = javascript; _hybridWebView = webView; } [Obsolete] public override bool ShouldOverrideUrlLoading(WebView view, string url) { view.LoadUrl(url); // 触发加载开始事件 _hybridWebView.OnPageLoading(); Toast.MakeText(Android.App.Application.Context, "Loading...", ToastLength.Long).Show(); Console.WriteLine("Page Changing Now.."); return true; } // 兼容高版本Android跳转回调 [Obsolete] public override bool ShouldOverrideUrlLoading(WebView view, IWebResourceRequest request) { view.LoadUrl(request.Url.ToString()); _hybridWebView.OnPageLoading(); return true; } public override void OnPageStarted(WebView view, string url, Android.Graphics.Bitmap favicon) { // 也可以在这触发加载开始事件,根据需求二选一 // _hybridWebView.OnPageLoading(); base.OnPageStarted(view, url, favicon); Console.WriteLine("Sayfa Doluyor."); } public override void OnPageFinished(WebView view, string url) { base.OnPageFinished(view, url); view.EvaluateJavascript(_javascript, null); // 触发加载结束事件 _hybridWebView.OnPageLoaded(); Console.WriteLine("Sayfa Doldu"); } }
3. 修改Android端 HybridWebViewRenderer 类
创建JavascriptWebViewClient时传入当前HybridWebView实例:
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e) { base.OnElementChanged(e); Control.Settings.JavaScriptEnabled = true; Control.Settings.SetAppCacheEnabled(true); Control.Settings.CacheMode = Android.Webkit.CacheModes.Normal; Control.Settings.SetRenderPriority(RenderPriority.High); Control.Settings.DomStorageEnabled = true; Control.Settings.LoadsImagesAutomatically = true; if (e.OldElement != null) { Control.RemoveJavascriptInterface("jsBridge"); ((HybridWebView)Element).Cleanup(); } if (e.NewElement != null) { // 构造JavascriptWebViewClient时新增HybridWebView参数 Control.SetWebViewClient(new JavascriptWebViewClient($"javascript: {JavascriptFunction}", (HybridWebView)Element)); Control.AddJavascriptInterface(new JsBridge(this), "jsBridge"); } }
4. 修改共享项目 MainPage.xaml.cs
订阅HybridWebView的加载事件,控制ActivityIndicator状态:
public MainPage() { InitializeComponent(); NavigationPage.SetHasNavigationBar(this, false); webViewElement.Source = "https://mywebsite.com/"; webViewElement.RegisterAction(ExecuteActionFromJavascript); _deviceFeaturesHelper = new DeviceFeaturesHelper(); // 新增订阅加载状态事件 webViewElement.PageLoading += (s, e) => { loading.IsVisible = true; loading.IsRunning = true; }; webViewElement.PageLoaded += (s, e) => { loading.IsVisible = false; loading.IsRunning = false; }; }
补充说明:如果你的场景下Xamarin.Forms自带的
Navigating/Navigated事件可以覆盖所有跳转场景,直接取消MainPage中对应方法里的指示器控制代码注释即可,无需修改原生端代码。
内容的提问来源于stack exchange,提问作者Elitor
相关产品推荐
相关产品推荐

