Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
A Xamarin.FormsWebView je zobrazení, které zobrazuje webový obsah a obsah HTML ve vaší aplikaci. Tento článek vysvětluje, jak vytvořit vlastní renderer, který rozšiřuje WebView povolení vyvolání kódu jazyka C#z JavaScriptu.
Každé Xamarin.Forms zobrazení má doprovodný renderer pro každou platformu, která vytvoří instanci nativního ovládacího prvku. WebView Když aplikace v iOSu Xamarin.Forms vykresluje aplikaci, WkWebViewRenderer vytvoří se instance třídy, která následně vytvoří instanci nativního WkWebView ovládacího prvku. Na platformě Android třída WebViewRenderer vytvoří instanci nativního WebView ovládacího prvku. V Univerzální platforma Windows (UPW) třída WebViewRenderer vytvoří instanci nativního WebView ovládacího prvku. Další informace o rendereru a nativních tříd ovládacích prvcích, které Xamarin.Forms řídí mapování, naleznete v tématu Renderer Základní třídy a nativní ovládací prvky.
Následující diagram znázorňuje vztah mezi View a odpovídajícími nativními ovládacími prvky, které ho implementují:

Proces vykreslování lze použít k implementaci přizpůsobení platformy vytvořením vlastního rendereru pro každou platformu WebView . Postup je následující:
HybridWebViewVytvořte vlastní ovládací prvek.- Spotřebujte
HybridWebViewz Xamarin.Forms. - Vytvořte vlastní renderer pro každou platformu
HybridWebView.
Každá položka se teď bude zabývat implementací rendereru HybridWebView Xamarin.FormsWebView , který vylepšuje povolení vyvolání kódu jazyka C# z JavaScriptu. Instance HybridWebView se použije k zobrazení stránky HTML, která uživatele požádá o zadání jeho jména. Když uživatel klikne na tlačítko HTML, vyvolá funkce JavaScriptu jazyk C# Action , která zobrazí automaticky otevírané okno obsahující jméno uživatele.
Další informace o procesu vyvolání jazyka C# z JavaScriptu najdete v tématu Vyvolání jazyka C# z JavaScriptu. Další informace o stránce HTML naleznete v tématu Vytvoření webové stránky.
Poznámka:
Funkce WebView JavaScriptu může vyvolat z jazyka C# a vrátit jakýkoli výsledek volajícímu kódu C#. Další informace najdete v tématu Vyvolání JavaScriptu.
Vytvoření HybridWebView
Vlastní HybridWebView ovládací prvek lze vytvořit podtřídou WebView třídy:
public class HybridWebView : WebView
{
Action<string> action;
public static readonly BindableProperty UriProperty = BindableProperty.Create(
propertyName: "Uri",
returnType: typeof(string),
declaringType: typeof(HybridWebView),
defaultValue: default(string));
public string Uri
{
get { return (string)GetValue(UriProperty); }
set { SetValue(UriProperty, value); }
}
public void RegisterAction(Action<string> callback)
{
action = callback;
}
public void Cleanup()
{
action = null;
}
public void InvokeAction(string data)
{
if (action == null || data == null)
{
return;
}
action.Invoke(data);
}
}
Vlastní HybridWebView ovládací prvek se vytvoří v projektu knihovny .NET Standard a definuje pro tento ovládací prvek následující rozhraní API:
- Vlastnost
Uri, která určuje adresu webové stránky, která se má načíst. - Metoda
RegisterAction, která zaregistruje ovládacíActionprvek. Registrovaná akce bude vyvolána z JavaScriptu obsaženého v souboru HTML odkazovaném prostřednictvímUrivlastnosti. - Metoda
CleanUp, která odebere odkaz na zaregistrovanýAction. - Metoda
InvokeAction, která vyvolá zaregistrovanýAction. Tato metoda bude volána z vlastního rendereru v každém projektu platformy.
Využití HybridWebView
Vlastní HybridWebView ovládací prvek lze odkazovat v XAML v projektu knihovny .NET Standard deklarováním oboru názvů pro jeho umístění a použitím předpony oboru názvů u vlastního ovládacího prvku. Následující příklad kódu ukazuje, jak HybridWebView může vlastní ovládací prvek využívat stránka XAML:
<ContentPage ...
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
x:Class="CustomRenderer.HybridWebViewPage"
Padding="0,40,0,0">
<local:HybridWebView x:Name="hybridWebView"
Uri="index.html" />
</ContentPage>
Předponu local oboru názvů lze pojmenovat cokoli. clr-namespace Hodnoty ale assembly musí odpovídat podrobnostem vlastního ovládacího prvku. Jakmile je obor názvů deklarován, předpona se použije k odkazování na vlastní ovládací prvek.
Následující příklad kódu ukazuje, jak HybridWebView může vlastní ovládací prvek využívat stránka jazyka C#:
public HybridWebViewPageCS()
{
var hybridWebView = new HybridWebView
{
Uri = "index.html"
};
// ...
Padding = new Thickness(0, 40, 0, 0);
Content = hybridWebView;
}
Instance HybridWebView se použije k zobrazení nativního webového ovládacího prvku na každé platformě. Uri Vlastnost je nastavena na soubor HTML, který je uložen v každém projektu platformy a který se zobrazí nativním webovým ovládacím prvku. Vykreslený kód HTML požádá uživatele, aby zadal své jméno, přičemž funkce JavaScriptu vyvolá jazyk C# Action v reakci na tlačítko HTML.
Zaregistruje HybridWebViewPage akci, která se má vyvolat z JavaScriptu, jak je znázorněno v následujícím příkladu kódu:
public partial class HybridWebViewPage : ContentPage
{
public HybridWebViewPage()
{
// ...
hybridWebView.RegisterAction(data => DisplayAlert("Alert", "Hello " + data, "OK"));
}
}
Tato akce volá metodu DisplayAlert k zobrazení modální automaticky otevírané okno, které zobrazí název zadaný na stránce HTML zobrazené HybridWebView instancí.
Do každého projektu aplikace je teď možné přidat vlastní renderer, který vylepšuje webové ovládací prvky platformy tím, že umožní vyvolání kódu jazyka C# z JavaScriptu.
Vytvoření vlastního rendereru na jednotlivých platformách
Proces vytvoření vlastní třídy rendereru je následující:
- Vytvořte podtřídu
WkWebViewRenderertřídy v iOSu a třídu v AndroiduWebViewRenderera UPW, která vykreslí vlastní ovládací prvek. - Přepište metodu
OnElementChanged, která vykreslí logiku zápisuWebView, aby ji přizpůsobila. Tato metoda je volána při vytvoření objektuHybridWebView. ExportRendererPřidejte atribut do vlastní třídy rendereru nebo AssemblyInfo.cs a určete, že se použije k vykreslení vlastního Xamarin.Forms ovládacího prvku. Tento atribut se používá k registraci vlastního rendereru v Xamarin.Forms.
Poznámka:
Pro většinu Xamarin.Forms prvků je volitelné poskytnout vlastní renderer v každém projektu platformy. Pokud není zaregistrovaný vlastní renderer, použije se výchozí renderer základní třídy ovládacího prvku. Vlastní renderery jsou však vyžadovány v každém projektu platformy při vykreslování prvku View .
Následující diagram znázorňuje zodpovědnosti jednotlivých projektů v ukázkové aplikaci spolu s relacemi mezi nimi:

Vlastní HybridWebView ovládací prvek se vykresluje pomocí tříd rendereru platformy, které jsou odvozeny od WkWebViewRenderer třídy v iOSu a třídy WebViewRenderer v Androidu a UPW. Výsledkem je vykreslení každého HybridWebView vlastního ovládacího prvku s nativními webovými ovládacími prvky, jak je znázorněno na následujících snímcích obrazovky:

Třídy WkWebViewRenderer WebViewRenderer zpřístupňují metodu OnElementChanged , která je volána při Xamarin.Forms vytvoření vlastního ovládacího prvku pro vykreslení odpovídajícího nativního webového ovládacího prvku. Tato metoda přebírá VisualElementChangedEventArgs parametr, který obsahuje OldElement a NewElement vlastnosti. Tyto vlastnosti představují Xamarin.Forms prvek, ke kterému byl renderer připojen, a Xamarin.Forms prvek, ke kterému je renderer připojen, v uvedeném pořadí. V ukázkové aplikaci OldElement bude vlastnost a NewElement vlastnost bude obsahovat odkaz na HybridWebView null instanci.
Přepsáná verze OnElementChanged metody, v každé třídě rendereru platformy, je místo k provedení přizpůsobení nativního webového ovládacího prvku. Odkaz na Xamarin.Forms vykreslovaný ovládací prvek lze získat prostřednictvím Element vlastnosti.
Každá vlastní třída rendereru je zdobena ExportRenderer atributem, který registruje renderer s Xamarin.Forms. Atribut má dva parametry – název typu vykreslovaného vlastního Xamarin.Forms ovládacího prvku a název typu vlastního rendereru. Předpona assembly atributu určuje, že atribut se vztahuje na celé sestavení.
Následující části popisuje strukturu webové stránky načtené jednotlivými nativními webovými ovládacími prvky, proces vyvolání jazyka C# z JavaScriptu a jeho implementaci v každé třídě vlastního vykreslovacího modulu platformy.
Vytvoření webové stránky
Následující příklad kódu ukazuje webovou stránku, která se zobrazí vlastním ovládacím HybridWebView prvku:
<html>
<body>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<h1>HybridWebView Test</h1>
<br />
Enter name: <input type="text" id="name">
<br />
<br />
<button type="button" onclick="javascript: invokeCSCode($('#name').val());">Invoke C# Code</button>
<br />
<p id="result">Result:</p>
<script type="text/javascript">function log(str) {
$('#result').text($('#result').text() + " " + str);
}
function invokeCSCode(data) {
try {
log("Sending Data:" + data);
invokeCSharpAction(data);
}
catch (err) {
log(err);
}
}</script>
</body>
</html>
Webová stránka umožňuje uživateli zadat jeho jméno do input elementu a poskytuje button prvek, který při kliknutí vyvolá kód jazyka C#. Proces, jak toho dosáhnout, je následující:
- Když uživatel klikne na
buttonprvek,invokeCSCodevolá se javascriptová funkce s hodnotouinputprvku, který se předá funkci. - Funkce
invokeCSCodevolálogfunkci, aby zobrazila data, která odesílá do jazyka C#Action. Potom volá metoduinvokeCSharpActionk vyvolání jazyka C#Actiona předání parametru přijatého z elementuinput.
Funkce JavaScriptu není definována invokeCSharpAction na webové stránce a bude do ní vložena jednotlivými vlastními renderery.
V iOSu se tento soubor HTML nachází ve složce Obsah projektu platformy s akcí sestavení BundleResource. V Androidu se tento soubor HTML nachází ve složce Assets/Content projektu platformy s akcí sestavení AndroidAsset.
Vyvolání jazyka C# z JavaScriptu
Proces vyvolání jazyka C# z JavaScriptu je stejný na každé platformě:
- Vlastní renderer vytvoří nativní webový ovládací prvek a načte soubor HTML určený
HybridWebView.Urivlastností. - Po načtení webové stránky vlastní renderer vloží
invokeCSharpActionfunkci JavaScriptu na webovou stránku. - Když uživatel zadá své jméno a klikne na element HTML
button,invokeCSCodevyvolá se funkce, která zase vyvoláinvokeCSharpActionfunkci. - Funkce
invokeCSharpActionvyvolá metodu ve vlastním rendereru, která následně vyvolá metoduHybridWebView.InvokeAction. - Metoda
HybridWebView.InvokeActionvyvolá zaregistrovanýAction.
V následujících částech se dozvíte, jak se tento proces implementuje na jednotlivých platformách.
Vytvoření vlastního rendereru v iOSu
Následující příklad kódu ukazuje vlastní renderer pro platformu iOS:
[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace CustomRenderer.iOS
{
public class HybridWebViewRenderer : WkWebViewRenderer, IWKScriptMessageHandler
{
const string JavaScriptFunction = "function invokeCSharpAction(data){window.webkit.messageHandlers.invokeAction.postMessage(data);}";
WKUserContentController userController;
public HybridWebViewRenderer() : this(new WKWebViewConfiguration())
{
}
public HybridWebViewRenderer(WKWebViewConfiguration config) : base(config)
{
userController = config.UserContentController;
var script = new WKUserScript(new NSString(JavaScriptFunction), WKUserScriptInjectionTime.AtDocumentEnd, false);
userController.AddUserScript(script);
userController.AddScriptMessageHandler(this, "invokeAction");
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
userController.RemoveAllUserScripts();
userController.RemoveScriptMessageHandler("invokeAction");
HybridWebView hybridWebView = e.OldElement as HybridWebView;
hybridWebView.Cleanup();
}
if (e.NewElement != null)
{
string filename = Path.Combine(NSBundle.MainBundle.BundlePath, $"Content/{((HybridWebView)Element).Uri}");
LoadRequest(new NSUrlRequest(new NSUrl(filename, false)));
}
}
public void DidReceiveScriptMessage(WKUserContentController userContentController, WKScriptMessage message)
{
((HybridWebView)Element).InvokeAction(message.Body.ToString());
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
((HybridWebView)Element).Cleanup();
}
base.Dispose(disposing);
}
}
}
Třída HybridWebViewRenderer načte webovou stránku zadanou ve HybridWebView.Uri vlastnosti do nativního WKWebView ovládacího prvku a invokeCSharpAction funkce JavaScriptu se vloží na webovou stránku. Jakmile uživatel zadá své jméno a klikne na element HTML button , invokeCSharpAction spustí se funkce JavaScriptu s DidReceiveScriptMessage metodou, která se volá po přijetí zprávy z webové stránky. Tato metoda zase vyvolá metodu HybridWebView.InvokeAction , která vyvolá zaregistrovanou akci, která zobrazí automaticky otevírané okno.
Tato funkce se dosahuje následujícím způsobem:
- Konstruktor rendereru
WkWebViewConfigurationvytvoří objekt a načte jehoWKUserContentControllerobjekt. ObjektWkUserContentControllerumožňuje publikovat zprávy a vkládat uživatelské skripty na webovou stránku. - Konstruktor rendereru
WKUserScriptvytvoří objekt, který vložíinvokeCSharpActionfunkci JavaScriptu na webovou stránku po načtení webové stránky. - Konstruktor renderer volá metodu
WKUserContentController.AddUserScriptpro přidáníWKUserScriptobjektu do kontroleru obsahu. - Konstruktor renderer volá metodu
WKUserContentController.AddScriptMessageHandlerpro přidání obslužné rutiny zprávy skriptu pojmenovanéinvokeActiondo objektuWKUserContentController, což způsobí, že javascriptová funkcewindow.webkit.messageHandlers.invokeAction.postMessage(data)bude definována ve všech rámcích ve všechWebViewinstancích, které objekt používajíWKUserContentController. - Za předpokladu, že je vlastní renderer připojený k novému Xamarin.Forms prvku:
- Metoda
WKWebView.LoadRequestnačte soubor HTML určenýHybridWebView.Urivlastností. Kód určuje, že soubor je uložen veContentsložce projektu. Po zobrazeníinvokeCSharpActionwebové stránky se funkce JavaScriptu vloží na webovou stránku.
- Metoda
- Prostředky jsou uvolněny, když je prvek renderer připojen ke změnám.
- Prvek Xamarin.Forms se vyčistí při uvolnění rendereru.
Poznámka:
Třída WKWebView je podporována pouze v iOSu 8 a novějším.
Kromě toho musí být soubor Info.plist aktualizován tak, aby obsahoval následující hodnoty:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Vytvoření vlastního rendereru v Androidu
Následující příklad kódu ukazuje vlastní renderer pro platformu Android:
[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace CustomRenderer.Droid
{
public class HybridWebViewRenderer : WebViewRenderer
{
const string JavascriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";
Context _context;
public HybridWebViewRenderer(Context context) : base(context)
{
_context = context;
}
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
Control.RemoveJavascriptInterface("jsBridge");
((HybridWebView)Element).Cleanup();
}
if (e.NewElement != null)
{
Control.SetWebViewClient(new JavascriptWebViewClient(this, $"javascript: {JavascriptFunction}"));
Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
Control.LoadUrl($"file:///android_asset/Content/{((HybridWebView)Element).Uri}");
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
((HybridWebView)Element).Cleanup();
}
base.Dispose(disposing);
}
}
}
Třída HybridWebViewRenderer načte webovou stránku zadanou ve HybridWebView.Uri vlastnosti do nativního WebView ovládacího prvku a invokeCSharpAction funkce JavaScriptu se vloží na webovou stránku po dokončení načítání webové stránky s OnPageFinished přepsání ve JavascriptWebViewClient třídě:
public class JavascriptWebViewClient : FormsWebViewClient
{
string _javascript;
public JavascriptWebViewClient(HybridWebViewRenderer renderer, string javascript) : base(renderer)
{
_javascript = javascript;
}
public override void OnPageFinished(WebView view, string url)
{
base.OnPageFinished(view, url);
view.EvaluateJavascript(_javascript, null);
}
}
Jakmile uživatel zadá své jméno a klikne na element HTML button , invokeCSharpAction spustí se funkce JavaScriptu. Tato funkce se dosahuje následujícím způsobem:
- Za předpokladu, že je vlastní renderer připojený k novému Xamarin.Forms prvku:
- Metoda
SetWebViewClientnastaví novýJavascriptWebViewClientobjekt jako implementaciWebViewClient. - Metoda
WebView.AddJavascriptInterfacevloží novouJSBridgeinstanci do hlavního rámce kontextu JavaScript WebView a pojme jejjsBridge. To umožňuje přístup k metodám veJSBridgetřídě z JavaScriptu. - Metoda
WebView.LoadUrlnačte soubor HTML určenýHybridWebView.Urivlastností. Kód určuje, že soubor je uložen veContentsložce projektu. JavascriptWebViewClientVe tříděinvokeCSharpActionse funkce JavaScriptu vloží na webovou stránku, jakmile se stránka dokončí načítání.
- Metoda
- Prostředky jsou uvolněny, když je prvek renderer připojen ke změnám.
- Prvek Xamarin.Forms se vyčistí při uvolnění rendereru.
invokeCSharpAction Když je funkce JavaScriptu spuštěna, pak vyvolá metoduJSBridge.InvokeAction, která je znázorněna v následujícím příkladu kódu:
public class JSBridge : Java.Lang.Object
{
readonly WeakReference<HybridWebViewRenderer> hybridWebViewRenderer;
public JSBridge(HybridWebViewRenderer hybridRenderer)
{
hybridWebViewRenderer = new WeakReference<HybridWebViewRenderer>(hybridRenderer);
}
[JavascriptInterface]
[Export("invokeAction")]
public void InvokeAction(string data)
{
HybridWebViewRenderer hybridRenderer;
if (hybridWebViewRenderer != null && hybridWebViewRenderer.TryGetTarget(out hybridRenderer))
{
((HybridWebView)hybridRenderer.Element).InvokeAction(data);
}
}
}
Třída musí být odvozena od Java.Lang.Objecta metody, které jsou vystaveny JavaScriptu, musí být zdobeny [JavascriptInterface] a [Export] atributy. Proto když je javascriptová invokeCSharpAction funkce vložena na webovou stránku a je spuštěna, zavolá metodu JSBridge.InvokeAction kvůli dekorování pomocí [JavascriptInterface] a [Export("invokeAction")] atributů. Metoda zase InvokeAction vyvolá metodu HybridWebView.InvokeAction , která vyvolá zaregistrovanou akci, která zobrazí automaticky otevírané okno.
Důležité
Projekty Androidu, které používají [Export] atribut, musí obsahovat odkaz na Mono.Android.Export, nebo chyba kompilátoru bude mít za následek.
Všimněte si, že třída JSBridge udržuje WeakReference třídu HybridWebViewRenderer . Tím se vyhnete vytváření cyklických odkazů mezi těmito dvěma třídami. Další informace naleznete v tématu Slabé odkazy.
Vytvoření vlastního rendereru v UPW
Následující příklad kódu ukazuje vlastní renderer pro UPW:
[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace CustomRenderer.UWP
{
public class HybridWebViewRenderer : WebViewRenderer
{
const string JavaScriptFunction = "function invokeCSharpAction(data){window.external.notify(data);}";
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
Control.NavigationCompleted -= OnWebViewNavigationCompleted;
Control.ScriptNotify -= OnWebViewScriptNotify;
}
if (e.NewElement != null)
{
Control.NavigationCompleted += OnWebViewNavigationCompleted;
Control.ScriptNotify += OnWebViewScriptNotify;
Control.Source = new Uri($"ms-appx-web:///Content//{((HybridWebView)Element).Uri}");
}
}
async void OnWebViewNavigationCompleted(Windows.UI.Xaml.Controls.WebView sender, WebViewNavigationCompletedEventArgs args)
{
if (args.IsSuccess)
{
// Inject JS script
await Control.InvokeScriptAsync("eval", new[] { JavaScriptFunction });
}
}
void OnWebViewScriptNotify(object sender, NotifyEventArgs e)
{
((HybridWebView)Element).InvokeAction(e.Value);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
((HybridWebView)Element).Cleanup();
}
base.Dispose(disposing);
}
}
}
Třída HybridWebViewRenderer načte webovou stránku zadanou ve HybridWebView.Uri vlastnosti do nativního WebView ovládacího prvku a invokeCSharpAction funkce JavaScriptu se vloží na webovou stránku po načtení webové stránky s metodou WebView.InvokeScriptAsync . Jakmile uživatel zadá své jméno a klikne na element HTML button , invokeCSharpAction spustí se funkce JavaScriptu s OnWebViewScriptNotify metodou, která se volá po přijetí oznámení z webové stránky. Tato metoda zase vyvolá metodu HybridWebView.InvokeAction , která vyvolá zaregistrovanou akci, která zobrazí automaticky otevírané okno.
Tato funkce se dosahuje následujícím způsobem:
- Za předpokladu, že je vlastní renderer připojený k novému Xamarin.Forms prvku:
- Obslužné rutiny událostí a
NavigationCompletedScriptNotifyudálosti jsou registrovány. UdálostNavigationCompletedse aktivuje, když nativníWebViewovládací prvek dokončil načítání aktuálního obsahu nebo pokud se navigace nezdařila. UdálostScriptNotifyse aktivuje, když obsah v nativnímWebViewovládacím prvku používá JavaScript k předání řetězce do aplikace. Webová stránka aktivujeScriptNotifyudálost volánímwindow.external.notifypři předávání parametrustring. - Vlastnost
WebView.Sourceje nastavena na identifikátor URI souboru HTML, který je určen vlastnostíHybridWebView.Uri. Kód předpokládá, že soubor je uložený veContentsložce projektu. Po zobrazeníNavigationCompletedwebové stránky se událost aktivuje aOnWebViewNavigationCompletedvyvolá se metoda. FunkceinvokeCSharpActionJavaScriptu se pak vloží na webovou stránku s metodouWebView.InvokeScriptAsyncza předpokladu, že navigace byla úspěšně dokončena.
- Obslužné rutiny událostí a
- Událost se odhlásí, když je prvek, který renderer připojí ke změnám.
- Prvek Xamarin.Forms se vyčistí při uvolnění rendereru.