Hi, everyone!
I want to create static WebView, which i can use on diffrent pages.
I created public static ExtWebView staticWebView but its dont help me, my webview loading again.
I have Renderer:
[assembly: ExportRenderer(typeof(ExtWebView), typeof(ExtWebViewRenderer))]
namespace DirectorixRoom.Droid
{
public class ExtWebViewRenderer : ViewRenderer<ExtWebView, AWebView>, IWebViewDelegate
{
bool _ignoreSourceChanges;
ExtFormsWebChromeClient _webChromeClient;
IWebViewController ElementController => Element;
public ExtWebViewRenderer(Context context) : base(context)
{
AutoPackage = false;
}
[Obsolete("This constructor is obsolete as of version 2.5. Please use WebViewRenderer(Context) instead.")]
public ExtWebViewRenderer()
{
AutoPackage = false;
}
public void LoadHtml(string html, string baseUrl)
{
Control.LoadDataWithBaseURL(baseUrl ?? "file:///android_asset/", html, "text/html", "UTF-8", null);
}
public void LoadUrl(string url)
{
Control.LoadUrl(url);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (Element != null)
{
if (Control != null)
Control.StopLoading();
ElementController.EvalRequested -= OnEvalRequested;
ElementController.GoBackRequested -= OnGoBackRequested;
ElementController.GoForwardRequested -= OnGoForwardRequested;
_webChromeClient?.Dispose();
}
}
base.Dispose(disposing);
}
protected virtual ExtFormsWebChromeClient GetFormsWebChromeClient()
{
return new ExtFormsWebChromeClient();
}
protected override Size MinimumSize()
{
return new Size(Context.ToPixels(40), Context.ToPixels(40));
}
protected override AWebView CreateNativeControl()
{
return new AWebView(Context);
}
protected override void OnElementChanged(ElementChangedEventArgs<ExtWebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
var webView = CreateNativeControl();
webView.LayoutParameters = new global::Android.Widget.AbsoluteLayout.LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent, 0, 0);
webView.SetWebViewClient(new WebClient(this));
_webChromeClient = GetFormsWebChromeClient();
_webChromeClient.SetContext(Context as Activity);
webView.SetWebChromeClient(_webChromeClient);
webView.Settings.JavaScriptEnabled = true;
webView.Settings.DomStorageEnabled = true;
webView.Settings.AllowFileAccessFromFileURLs = true;
SetNativeControl(webView);
}
if (e.OldElement != null)
{
var oldElementController = e.OldElement as IWebViewController;
oldElementController.EvalRequested -= OnEvalRequested;
oldElementController.EvaluateJavaScriptRequested -= OnEvaluateJavaScriptRequested;
oldElementController.GoBackRequested -= OnGoBackRequested;
oldElementController.GoForwardRequested -= OnGoForwardRequested;
Control.RemoveJavascriptInterface("mapEvents");
}
if (e.NewElement != null)
{
var newElementController = e.NewElement as IWebViewController;
newElementController.EvalRequested += OnEvalRequested;
newElementController.EvaluateJavaScriptRequested += OnEvaluateJavaScriptRequested;
newElementController.GoBackRequested += OnGoBackRequested;
newElementController.GoForwardRequested += OnGoForwardRequested;
Control.AddJavascriptInterface(new JSBridge(this), "mapEvents");
Control.LoadUrl($"file://{System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData)}/webgl/map.html");
UpdateMixedContentMode();
}
Load();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
switch (e.PropertyName)
{
case "Source":
Load();
break;
case "MixedContentMode":
UpdateMixedContentMode();
break;
}
}
void Load()
{
if (_ignoreSourceChanges)
return;
if (Element.Source != null)
Element.Source.Load(this);
UpdateCanGoBackForward();
}
void OnEvalRequested(object sender, EvalRequested eventArg)
{
LoadUrl("javascript:" + eventArg.Script);
}
async Task<string> OnEvaluateJavaScriptRequested(string script)
{
var jsr = new JavascriptResult();
Control.EvaluateJavascript(script, jsr);
return await jsr.JsResult.ConfigureAwait(false);
}
void OnGoBackRequested(object sender, EventArgs eventArgs)
{
if (Control.CanGoBack())
Control.GoBack();
UpdateCanGoBackForward();
}
void OnGoForwardRequested(object sender, EventArgs eventArgs)
{
if (Control.CanGoForward())
Control.GoForward();
UpdateCanGoBackForward();
}
void UpdateCanGoBackForward()
{
if (Element == null || Control == null)
return;
ElementController.CanGoBack = Control.CanGoBack();
ElementController.CanGoForward = Control.CanGoForward();
}
void UpdateMixedContentMode()
{
if (Control != null && ((int)Build.VERSION.SdkInt >= 21))
{
if (Element is Xamarin.Forms.WebView element)
{
Control.Settings.MixedContentMode = (MixedContentHandling)element.OnThisPlatform().MixedContentMode();
}
else
{
throw new InvalidCastException("Element type is not based on Xamarin.Forms.WebView");
}
}
}
class WebClient : WebViewClient
{
WebNavigationResult _navigationResult = WebNavigationResult.Success;
ExtWebViewRenderer _renderer;
public WebClient(ExtWebViewRenderer renderer)
{
_renderer = renderer ?? throw new ArgumentNullException("renderer");
}
public override void OnPageFinished(AWebView view, string url)
{
if (_renderer.Element == null || url == "file:///android_asset/")
return;
var source = new UrlWebViewSource { Url = url };
_renderer._ignoreSourceChanges = true;
_renderer.ElementController.SetValueFromRenderer(ExtWebView.SourceProperty, source);
_renderer._ignoreSourceChanges = false;
var args = new WebNavigatedEventArgs(WebNavigationEvent.NewPage, source, url, _navigationResult);
_renderer.ElementController.SendNavigated(args);
_renderer.UpdateCanGoBackForward();
base.OnPageFinished(view, url);
}
[Obsolete("OnReceivedError is obsolete as of version 2.3.0. This method was deprecated in API level 23.")]
public override void OnReceivedError(AWebView view, ClientError errorCode, string description, string failingUrl)
{
_navigationResult = WebNavigationResult.Failure;
if (errorCode == ClientError.Timeout)
_navigationResult = WebNavigationResult.Timeout;
base.OnReceivedError(view, errorCode, description, failingUrl);
}
public override void OnReceivedError(AWebView view, IWebResourceRequest request, WebResourceError error)
{
_navigationResult = WebNavigationResult.Failure;
if (error.ErrorCode == ClientError.Timeout)
_navigationResult = WebNavigationResult.Timeout;
base.OnReceivedError(view, request, error);
}
[Obsolete]
public override bool ShouldOverrideUrlLoading(AWebView view, string url)
{
if (_renderer.Element == null)
return true;
var args = new WebNavigatingEventArgs(WebNavigationEvent.NewPage, new UrlWebViewSource { Url = url }, url);
_renderer.ElementController.SendNavigating(args);
_navigationResult = WebNavigationResult.Success;
_renderer.UpdateCanGoBackForward();
return args.Cancel;
}
#region Added overrides
public override void DoUpdateVisitedHistory(AWebView view, string url, bool isReload)
{
base.DoUpdateVisitedHistory(view, url, isReload);
}
public override void OnFormResubmission(AWebView view, Message dontResend, Message resend)
{
base.OnFormResubmission(view, dontResend, resend);
}
public override void OnLoadResource(AWebView view, string url)
{
base.OnLoadResource(view, url);
}
public override void OnPageCommitVisible(AWebView view, string url)
{
base.OnPageCommitVisible(view, url);
}
public override void OnPageStarted(AWebView view, string url, Bitmap favicon)
{
base.OnPageStarted(view, url, favicon);
}
public override void OnReceivedClientCertRequest(AWebView view, ClientCertRequest request)
{
base.OnReceivedClientCertRequest(view, request);
}
public override void OnReceivedHttpAuthRequest(AWebView view, HttpAuthHandler handler, string host, string realm)
{
base.OnReceivedHttpAuthRequest(view, handler, host, realm);
}
public override void OnReceivedHttpError(AWebView view, IWebResourceRequest request, WebResourceResponse errorResponse)
{
base.OnReceivedHttpError(view, request, errorResponse);
}
public override void OnReceivedLoginRequest(AWebView view, string realm, string account, string args)
{
base.OnReceivedLoginRequest(view, realm, account, args);
}
public override void OnReceivedSslError(AWebView view, SslErrorHandler handler, SslError error)
{
base.OnReceivedSslError(view, handler, error);
}
public override bool OnRenderProcessGone(AWebView view, RenderProcessGoneDetail detail)
{
return base.OnRenderProcessGone(view, detail);
}
public override void OnSafeBrowsingHit(AWebView view, IWebResourceRequest request, [GeneratedEnum] SafeBrowsingThreat threatType, SafeBrowsingResponse callback)
{
base.OnSafeBrowsingHit(view, request, threatType, callback);
}
public override void OnScaleChanged(AWebView view, float oldScale, float newScale)
{
base.OnScaleChanged(view, oldScale, newScale);
}
[Obsolete]
public override void OnTooManyRedirects(AWebView view, Message cancelMsg, Message continueMsg)
{
base.OnTooManyRedirects(view, cancelMsg, continueMsg);
}
public override void OnUnhandledInputEvent(AWebView view, InputEvent e)
{
base.OnUnhandledInputEvent(view, e);
}
public override void OnUnhandledKeyEvent(AWebView view, KeyEvent e)
{
base.OnUnhandledKeyEvent(view, e);
}
public override WebResourceResponse ShouldInterceptRequest(AWebView view, IWebResourceRequest request)
{
return base.ShouldInterceptRequest(view, request);
}
[Obsolete]
public override WebResourceResponse ShouldInterceptRequest(AWebView view, string url)
{
return base.ShouldInterceptRequest(view, url);
}
public override bool ShouldOverrideKeyEvent(AWebView view, KeyEvent e)
{
return base.ShouldOverrideKeyEvent(view, e);
}
public override bool ShouldOverrideUrlLoading(AWebView view, IWebResourceRequest request)
{
return base.ShouldOverrideUrlLoading(view, request);
}
#endregion
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
_renderer = null;
}
}
class JavascriptResult : Java.Lang.Object, IValueCallback
{
TaskCompletionSource<string> source;
public Task<string> JsResult { get { return source.Task; } }
public JavascriptResult()
{
source = new TaskCompletionSource<string>();
}
public void OnReceiveValue(Java.Lang.Object result)
{
string json = ((Java.Lang.String)result).ToString();
source.SetResult(json);
}
}
}
}