You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.09 16:24:02