I'm currently developing an app in Xamarin Forms with an Android background so I wanted to create an Android app first and an iOS app later.
I'm new to Xamarin Forms and I'm struggling on how to update a ProgressBar from a WebView using a custom renderer for the WebView
.
In Android, you can do something like this, with the ProgressBar and WebView that are in the main_layout.xml
public class MainActivity extends Activity { private ProgressBar progressBar; private WebView webView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_layout); progressBar = (ProgressBar) findViewById(R.id.progress); webView = (AdvancedWebView) findViewById(R.id.webView); // webview initialisation webView.setWebChromeClient(new WebChromeClient(){ @Override public void onProgressChanged(WebView view, int newProgress) { // update progressbar progress progressBar.setProgress(newProgress); } }); webView.setWebViewClient(new WebViewClient(this) { @Override public void onPageFinished(WebView view, String url) { // hide progressbar when it's done progressBar.setVisibility(View.GONE); } }); } }
In Xamarin Forms I have this layout in MainPage.xaml in the shared project
<?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="MainPage" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" NavigationPage.HasNavigationBar="False"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="*" /> <RowDefinition Height="*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <ProgressBar x:Name="progress" Grid.Row="3" HorizontalOptions="FillAndExpand" Progress="0" VerticalOptions="Center" /> <WebView x:Name="webview" Grid.Row="0" Grid.RowSpan="4" Grid.Column="0" HorizontalOptions="FillAndExpand" IsVisible="False" Source="https://google.com" VerticalOptions="FillAndExpand" /> </Grid>
public partial class App : Application { public App () { InitializeComponent(); MainPage = new MainPage(); } }
And this custom WebView render for android in the android project
[assembly: ExportRenderer(typeof(WebView), typeof(CustomWebviewRenderer))] namespace MyApp.Droid { public class CustomWebviewRenderer: WebViewRenderer { private readonly Context context; public CustomWebviewRenderer(Context context) : base(context) { this.context = context; } protected override void OnElementChanged(ElementChangedEventArgs<WebView> e) { base.OnElementChanged(e); var formsWebView = e.NewElement as Xamarin.Forms.WebView; if (formsWebView != null) { var webView = Control as Android.Webkit.WebView; webView.SetWebViewClient(new CustomWebViewClient()); webView.SetWebChromeClient(new CustomWebChromeClient()); webView.Settings.LoadWithOverviewMode = true; webView.Settings.UseWideViewPort = true; SetNativeControl(webView); } } private class ScoritoWebChromeClient : WebChromeClient { public override void OnProgressChanged(Android.Webkit.WebView view, int newProgress) { // how to update progressbar progress? base.OnProgressChanged(view, newProgress); } } private class CustomWebViewClient : WebViewClient { public override void OnPageFinished(Android.Webkit.WebView view, string url) { // how to hide progressbar? base.OnPageFinished(view, url); } public override void OnPageStarted(Android.Webkit.WebView view, string url, Bitmap favicon) { base.OnPageStarted(view, url, favicon); } public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, IWebResourceRequest request) { return base.ShouldOverrideUrlLoading(view, request); } } } }
How can I update the ProgressBar that I have in my MainPage.xaml from the OnPageFinished
in the CustomWebviewRenderer
class to show the webpage has finished loading? Should I use the MainActivity.cs in the Android project?
Can someone point me in the right direction on how to solve this?
1 Answers
Answers 1
You don't need custom renderers for what you are doing first and foremost.
Why don't you use the Navigating & Navigated Binding's in your Xamarin forms Webview?
<WebView x:Name="Webview" Navigating="OnNavigating" Navigated="OnNavigated" VerticalOptions="FillAndExpand"/>
And then do this in your xaml.cs:
protected async override void OnAppearing() { base.OnAppearing(); await progress.ProgressTo(0.9, 900, Easing.SpringIn); } private void OnNavigated(object sender, Xamarin.Forms.WebNavigatedEventArgs e) { progress.IsVisible = false; } private void OnNavigating(object sender, Xamarin.Forms.WebNavigatingEventArgs e) { progress.IsVisible = true; }
And this should be enough
But if you still insist to use your renderer what you can do is update the progress bar using the element property and get a callback or change a property something like below:
[assembly: ExportRenderer(typeof(WebView), typeof(CustomWebviewRenderer))] namespace MyApp.Droid { public class CustomWebviewRenderer: WebViewRenderer { private readonly Context context; private MainPage MainPage { get { var mainPage = Element as MainPage; return mainPage == null ? null : mainPage; } } public CustomWebviewRenderer(Context context) : base(context) { this.context = context; } protected override void OnElementChanged(ElementChangedEventArgs<WebView> e) { base.OnElementChanged(e); var formsWebView = e.NewElement as Xamarin.Forms.WebView; if (formsWebView != null) { var webView = Control as Android.Webkit.WebView; webView.SetWebViewClient(new CustomWebViewClient()); webView.SetWebChromeClient(new CustomWebChromeClient()); webView.Settings.LoadWithOverviewMode = true; webView.Settings.UseWideViewPort = true; SetNativeControl(webView); } } private class ScoritoWebChromeClient : WebChromeClient { public override void OnProgressChanged(Android.Webkit.WebView view, int newProgress) { // how to update progressbar progress? base.OnProgressChanged(view, newProgress); } } private class CustomWebViewClient : WebViewClient { public override void OnPageFinished(Android.Webkit.WebView view, string url) { // how to hide progressbar? MainPage.yourCallbackFunc(); base.OnPageFinished(view, url); } public override void OnPageStarted(Android.Webkit.WebView view, string url, Bitmap favicon) { base.OnPageStarted(view, url, favicon); } public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, IWebResourceRequest request) { return base.ShouldOverrideUrlLoading(view, request); } } } }
And get the callback in that xamarin forms page:
public partial class MainPage: ContentPage { public MainPage() { InitializeComponent(); } public void yourCallbackFunc() { . . // Do some functionality . } }
In case it doesn't work or you have queries revert!
0 comments:
Post a Comment