如何在加载数据时获取WebView的进度,Xamarin.Forms

Xhu*_*lio 10 progress webview progress-bar xamarin.forms

我正在使用Xamarin.Forms开发一个应用程序来列出来自不同来源的新闻.我使用webView打开与新闻相对应的链接.但我希望在将网页加载到Web视图时显示进度,例如Safari App上的进度条.为此,我使用了ProgressBar元素,如下所示:

<StackLayout>
            <!-- WebView needs to be given height and width request within layouts to render. -->

            <ProgressBar Progress ="" HorizontalOptions="FillAndExpand" x:Name="progress"/>
            <WebView x:Name="webView" 
                     HeightRequest="1000"
                     WidthRequest="1000"  
                     VerticalOptions= "FillAndExpand" 
                     Navigating="webOnNavigating"
                     Navigated="webOnEndNavigating"/>
        </StackLayout>
Run Code Online (Sandbox Code Playgroud)

并在我使用的代码中

void webOnNavigating (object sender, WebNavigatingEventArgs e)
        {
            progress.IsVisible = true;

        }

        void webOnEndNavigating (object sender, WebNavigatedEventArgs e)
        {
            progress.IsVisible = false;
        }
Run Code Online (Sandbox Code Playgroud)

但我想展示加载数据的进度,而不仅仅是加载和加载的指示.我希望用户知道数据正在加载.有没有办法实现这一目标.

EvZ*_*EvZ 2

实现应该通过自定义渲染来实现特定于平台的。幸运的是,这个主题已经在 SO 上针对不同平台进行了讨论。

基于此线程的 Android 版本:

[assembly: ExportRenderer(typeof(WebView), typeof(GenericWebViewRenderer))]
namespace WebViewWithProgressBar.Droid
{
    public class GenericWebViewRenderer : WebViewRenderer
    {
        Context ctx;

        public GenericWebViewRenderer(Context context) : base(context) 
        {
            ctx = context;
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
                return;

            var progressBar = new Android.Widget.ProgressBar(ctx, null, Android.Resource.Attribute.ProgressBarStyleHorizontal);
            Control.SetWebChromeClient(new MyWebChromeClient(progressBar));

            Control.AddView(progressBar);
        }

        class MyWebChromeClient : Android.Webkit.WebChromeClient
        {
            Android.Widget.ProgressBar progressBar;

            public MyWebChromeClient(Android.Widget.ProgressBar progressBar)
            {
                this.progressBar = progressBar;
            }

            public override void OnProgressChanged(Android.Webkit.WebView view, int newProgress)
            {
                progressBar.SetProgress(newProgress, true);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在 iOS 上,这有点棘手,这里有一个非常简单的模拟,效果很好:

[assembly: ExportRenderer(typeof(WebView), typeof(GenericWebViewRenderer))]
namespace WebViewWithProgressBar.iOS
{
    public class GenericWebViewRenderer : ViewRenderer<WebView, UIWebView> 
    {
        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
            {
                var progressBar = new UIProgressView(UIProgressViewStyle.Bar);
                progressBar.TintColor = UIColor.Green;
                progressBar.TrackTintColor = UIColor.Black;
                progressBar.ProgressTintColor = UIColor.Red;

                var webView = new UIWebView(Frame);

                webView.AddSubview(progressBar);

                SetNativeControl(webView);

                Control.Delegate = new MyUIWebViewDelegate(progressBar);

                webView.LoadRequest(new NSUrlRequest(new NSUrl("https://google.com")));
            }
        }

        class MyUIWebViewDelegate : UIWebViewDelegate
        {
            UIProgressView progressBar { get; }

            public MyUIWebViewDelegate(UIProgressView progressBar)
            {
                this.progressBar = progressBar;
            }

            public override void LoadStarted(UIWebView webView)
            {
                progressBar.SetProgress(0.1f, false);
            }

            public override void LoadingFinished(UIWebView webView)
            {
                progressBar.SetProgress(1.0f, true);
            }

            public override void LoadFailed(UIWebView webView, NSError error)
            {
                // TODO:
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

欲了解更多详情,请查看此处

PS:此代码示例可在github上找到。