Xamarin.Forms Webview

Scaricare l'esempio Scaricare l'esempio

WebView è una visualizzazione per la visualizzazione di contenuto Web e HTML nell'app:

Nel browser dell'app

Content

WebView supporta i tipi di contenuto seguenti:

  • Siti & Web CSS HTML: WebView include il supporto completo per i siti Web scritti con CSS & HTML, incluso il supporto JavaScript.
  • Documenti: poiché WebView viene implementato usando componenti nativi in ogni piattaforma, WebView è in grado di visualizzare i documenti nei formati supportati dalla piattaforma sottostante.
  • Stringhe HTML: WebView può visualizzare stringhe HTML dalla memoria.
  • File locali: WebView può presentare qualsiasi tipo di contenuto sopra incorporato nell'app.

Nota

WebViewin Windows supporta Silverlight, Flash o qualsiasi controllo ActiveX, anche se sono supportati da Internet Explorer su tale piattaforma.

Siti Web

Per visualizzare un sito Web da Internet, impostare la WebView proprietà di su un URL Source stringa:

var browser = new WebView
{
  Source = "https://dotnet.microsoft.com/apps/xamarin"
};

Nota

Gli URL devono essere completamente formati con il protocollo specificato,ad esempio deve essere preceduto da "http://" o "https://".

iOS e ATS

A partire dalla versione 9, iOS consentirà all'applicazione di comunicare solo con i server che implementano la sicurezza delle procedure consigliate per impostazione predefinita. I valori devono essere impostati in Info.plist per consentire la comunicazione con server non sicuri.

Nota

Se l'applicazione richiede una connessione a un sito Web non sicuro, è sempre necessario immettere il dominio come eccezione usando invece di disattivare completamente NSExceptionDomains ATS usando NSAllowsArbitraryLoads . NSAllowsArbitraryLoads deve essere usato solo in situazioni di emergenza estrema.

Di seguito viene illustrato come abilitare un dominio specifico (in questo caso xamarin.com) per ignorare i requisiti di ATS:

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>xamarin.com</key>
            <dict>
                <key>NSIncludesSubdomains</key>
                <true/>
                <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSTemporaryExceptionMinimumTLSVersion</key>
                <string>TLSv1.1</string>
            </dict>
        </dict>
    </dict>
    ...
</key>

È consigliabile consentire solo ad alcuni domini di ignorare ATS, consentendo di usare siti attendibili, traendo vantaggio dalla sicurezza aggiuntiva nei domini non attendibili. Di seguito viene illustrato il metodo meno sicuro di disabilitazione di ATS per l'app:

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads </key>
        <true/>
    </dict>
    ...
</key>

Per altre informazioni su questa nuova funzionalità in iOS 9, vedere App Transport Security.

Stringhe HTML

Se si vuole presentare una stringa di codice HTML definita dinamicamente nel codice, è necessario creare un'istanza di HtmlWebViewSource :

var browser = new WebView();
var htmlSource = new HtmlWebViewSource();
htmlSource.Html = @"<html><body>
  <h1>Xamarin.Forms</h1>
  <p>Welcome to WebView.</p>
  </body></html>";
browser.Source = htmlSource;

Visualizzazione di una stringa HTML in WebView

Nel codice precedente viene usato per contrassegnare il codice HTML come valore letterale stringa verbatim, vale a dire che la maggior parte dei caratteri @ di escape viene ignorata. @

Nota

Potrebbe essere necessario impostare le proprietà e di per visualizzare il contenuto HTML, a seconda del layout di WidthRequestHeightRequest di cui è WebViewWebView figlio. Ad esempio, questa operazione è necessaria in un StackLayout oggetto .

Contenuto HTML locale

WebView può visualizzare contenuto da HTML, CSS e JavaScript incorporati all'interno dell'app. Ad esempio:

<html>
  <head>
    <title>Xamarin Forms</title>
  </head>
  <body>
    <h1>Xamarin.Forms</h1>
    <p>This is an iOS web page.</p>
    <img src="XamarinLogo.png" />
  </body>
</html>

CSS:

html,body {
  margin:0;
  padding:10;
}
body,p,h1 {
  font-family: Chalkduster;
}

Si noti che i tipi di carattere specificati nel css precedente dovranno essere personalizzati per ogni piattaforma, perché non tutte le piattaforme hanno gli stessi tipi di carattere.

Per visualizzare il contenuto locale usando , è necessario aprire il file HTML come qualsiasi altro, quindi caricare il contenuto come stringa nella proprietà WebViewHtml di un oggetto HtmlWebViewSource . Per altre informazioni sull'apertura di file, vedere Utilizzo dei file.

Gli screenshot seguenti mostrano il risultato della visualizzazione del contenuto locale in ogni piattaforma:

Visualizzazione di contenuto locale in WebView

Anche se la prima pagina è stata caricata, non ha alcuna conoscenza della origine WebView del codice HTML. Questo è un problema quando si gestiscono pagine che fanno riferimento a risorse locali. Esempi di quando ciò può verificarsi includono quando le pagine locali si collegano tra loro, una pagina usa un file JavaScript separato o un collegamento di pagina a un foglio di stile CSS.

Per risolvere questo problema, è necessario indicare a WebView dove trovare i file nel file system. A tale scopo, impostare BaseUrl la proprietà HtmlWebViewSource sull'oggetto utilizzato dall'oggetto WebView .

Poiché il file system in ogni sistema operativo è diverso, è necessario determinare l'URL in ogni piattaforma. Xamarin.Forms espone l'oggetto DependencyService per la risoluzione delle dipendenze in fase di esecuzione in ogni piattaforma.

Per usare DependencyService , definire innanzitutto un'interfaccia che possa essere implementata in ogni piattaforma:

public interface IBaseUrl { string Get(); }

Si noti che fino a quando l'interfaccia non viene implementata in ogni piattaforma, l'app non verrà eseguita. Nel progetto comune assicurarsi di ricordare di impostare usando BaseUrlDependencyService :

var source = new HtmlWebViewSource();
source.BaseUrl = DependencyService.Get<IBaseUrl>().Get();

È quindi necessario fornire implementazioni dell'interfaccia per ogni piattaforma.

iOS

In iOS il contenuto Web deve trovarsi nella directory radice del progetto o nella directory Resources con l'azione di compilazione BundleResource,come illustrato di seguito:

Deve BaseUrl essere impostato sul percorso del bundle principale:

[assembly: Dependency (typeof (BaseUrl_iOS))]
namespace WorkingWithWebview.iOS
{
  public class BaseUrl_iOS : IBaseUrl
  {
    public string Get()
    {
      return NSBundle.MainBundle.BundlePath;
    }
  }
}

Android

In Android posizionare HTML, CSS e immagini nella cartella Assets con l'azione di compilazione AndroidAsset, come illustrato di seguito:

In Android, BaseUrl deve essere impostato su "file:///android_asset/" :

[assembly: Dependency (typeof(BaseUrl_Android))]
namespace WorkingWithWebview.Android
{
  public class BaseUrl_Android : IBaseUrl
  {
    public string Get()
    {
      return "file:///android_asset/";
    }
  }
}

In Android è possibile accedere ai file nella cartella Assets anche tramite il contesto Android corrente, esposto dalla proprietà :

var assetManager = MainActivity.Instance.Assets;
using (var streamReader = new StreamReader (assetManager.Open ("local.html")))
{
  var html = streamReader.ReadToEnd ();
}

Piattaforma UWP (Universal Windows Platform)

Nei progetti UWP (Universal Windows Platform) posizionare HTML, CSS e immagini nella radice del progetto con l'azione di compilazione impostata su Contenuto.

Deve BaseUrl essere impostato su "ms-appx-web:///" :

[assembly: Dependency(typeof(BaseUrl))]
namespace WorkingWithWebview.UWP
{
    public class BaseUrl : IBaseUrl
    {
        public string Get()
        {
            return "ms-appx-web:///";
        }
    }
}

WebView supporta la navigazione tra diversi metodi e proprietà che rende disponibili:

  • GoForward(): se è true, la chiamata a consente di passare alla pagina GoForward visitata successiva.
  • GoBack(): se è true, la chiamata GoBack a consente di passare all'ultima pagina visitata.
  • CanGoBack: se sono presenti pagine a cui tornare, false se il browser si trova all'URL iniziale.
  • CanGoForward: se l'utente si è spostato all'indietro e può passare a una pagina già visitata.

All'interno WebView delle pagine, non supporta i movimenti multitocchetto. È importante assicurarsi che il contenuto sia ottimizzato per i dispositivi mobili e venga visualizzato senza la necessità di eseguire lo zoom.

È comune che le applicazioni mostrino un collegamento all'interno di un oggetto WebView anziché nel browser del dispositivo. In queste situazioni è utile consentire la navigazione normale, ma quando l'utente torna indietro mentre si trova sul collegamento iniziale, l'app dovrebbe tornare alla visualizzazione normale dell'app.

Usare le proprietà e i metodi di navigazione predefiniti per abilitare questo scenario.

Per iniziare, creare la pagina per la visualizzazione del browser:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="WebViewSample.InAppBrowserXaml"
             Title="Browser">
    <StackLayout Margin="20">
        <StackLayout Orientation="Horizontal">
            <Button Text="Back" HorizontalOptions="StartAndExpand" Clicked="OnBackButtonClicked" />
            <Button Text="Forward" HorizontalOptions="EndAndExpand" Clicked="OnForwardButtonClicked" />
        </StackLayout>
        <!-- WebView needs to be given height and width request within layouts to render. -->
        <WebView x:Name="webView" WidthRequest="1000" HeightRequest="1000" />
    </StackLayout>
</ContentPage>

Nel code-behind:

public partial class InAppBrowserXaml : ContentPage
{
    public InAppBrowserXaml(string URL)
    {
        InitializeComponent();
        webView.Source = URL;
    }

    async void OnBackButtonClicked(object sender, EventArgs e)
    {
        if (webView.CanGoBack)
        {
            webView.GoBack();
        }
        else
        {
            await Navigation.PopAsync();
        }
    }

    void OnForwardButtonClicked(object sender, EventArgs e)
    {
        if (webView.CanGoForward)
        {
            webView.GoForward();
        }
    }
}

Questo è tutto.

Pulsanti di spostamento di WebView

Eventi

WebView genera gli eventi seguenti per rispondere alle modifiche dello stato:

  • Navigating : evento generato quando WebView inizia a caricare una nuova pagina.
  • Navigated : evento generato quando la pagina viene caricata e la navigazione è stata arrestata.
  • ReloadRequested : evento generato quando viene effettuata una richiesta per ricaricare il contenuto corrente.

WebNavigatingEventArgsL'oggetto che accompagna Navigating l'evento ha quattro proprietà:

  • Cancel : indica se annullare o meno la navigazione.
  • NavigationEvent : evento di navigazione generato.
  • Source : elemento che ha eseguito la navigazione.
  • Url : destinazione di navigazione.

WebNavigatedEventArgsL'oggetto che accompagna Navigated l'evento ha quattro proprietà:

  • NavigationEvent : evento di navigazione generato.
  • Result : descrive il risultato della navigazione, usando un membro WebNavigationResult di enumerazione. I valori validi sono Cancel, Failure, Success e Timeout.
  • Source : elemento che ha eseguito la navigazione.
  • Url : destinazione di navigazione.

Se si prevede di usare pagine Web che richiedere molto tempo per il caricamento, è consigliabile usare gli Navigating eventi e Navigated per implementare un indicatore di stato. Ad esempio:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="WebViewSample.LoadingLabelXaml"
             Title="Loading Demo">
    <StackLayout>
        <!--Loading label should not render by default.-->
        <Label x:Name="labelLoading" Text="Loading..." IsVisible="false" />
        <WebView HeightRequest="1000" WidthRequest="1000" Source="https://dotnet.microsoft.com/apps/xamarin" Navigated="webviewNavigated" Navigating="webviewNavigating" />
    </StackLayout>
</ContentPage>

I due gestori eventi:

void webviewNavigating(object sender, WebNavigatingEventArgs e)
{
    labelLoading.IsVisible = true;
}

void webviewNavigated(object sender, WebNavigatedEventArgs e)
{
    labelLoading.IsVisible = false;
}

Verrà restituito l'output seguente (caricamento):

Screenshot che mostra l'evento di navigazione di WebView durante il caricamento.

Caricamento completato:

Screenshot che mostra l'evento di navigazione di WebView dopo il caricamento.

Ricaricamento del contenuto

WebView dispone di Reload un metodo che può essere usato per ricaricare il contenuto corrente:

var webView = new WebView();
...
webView.Reload();

Quando il metodo viene richiamato, viene generato l'evento , che indica che è stata effettuata una richiesta ReloadReloadRequested per ricaricare il contenuto corrente.

Prestazioni

I Web browser più diffusi adottano tecnologie come il rendering accelerato hardware e la compilazione JavaScript. Prima della Xamarin.Forms versione 4.4, Xamarin.FormsWebView l'oggetto è stato implementato in iOS dalla UIWebView classe . Tuttavia, molte di queste tecnologie non erano disponibili in questa implementazione. Pertanto, a partire dalla versione 4.4, l'oggetto viene implementato in iOS dalla classe , che Xamarin.FormsXamarin.FormsWebViewWkWebView supporta l'esplorazione più veloce.

Nota

In iOS dispone WkWebViewRenderer di un overload del costruttore che accetta un WkWebViewConfiguration argomento. In questo modo il renderer può essere configurato al momento della creazione.

Un'applicazione può tornare a usando la classe iOS UIWebView per implementare Xamarin.FormsWebView , per motivi di compatibilità. A tale scopo, aggiungere il codice seguente al file AssemblyInfo.cs nel progetto di piattaforma iOS per l'applicazione:

// Opt-in to using UIWebView instead of WkWebView.
[assembly: ExportRenderer(typeof(Xamarin.Forms.WebView), typeof(Xamarin.Forms.Platform.iOS.WebViewRenderer))]

Nota

Nella Xamarin.Forms versione 5.0 la WebViewRenderer classe è stata rimossa. Pertanto, Xamarin.Forms la versione 5.0 non contiene un riferimento al UIWebView controllo .

WebView in Android per impostazione predefinita è veloce quanto il browser predefinito.

WebView UWP usa il motore Microsoft Edge rendering. I dispositivi desktop e tablet dovrebbero avere le stesse prestazioni dell'uso del browser Edge stesso.

Autorizzazioni

Per il WebView funzionamento, è necessario assicurarsi che le autorizzazioni siano impostate per ogni piattaforma. Si noti che in alcune piattaforme funzionerà WebView in modalità di debug, ma non quando viene compilato per il rilascio. Ciò è dovuto al fatto che alcune autorizzazioni, come quelle per l'accesso a Internet in Android, vengono impostate per impostazione predefinita Visual Studio per Mac in modalità di debug.

  • UWP: richiede la funzionalità Internet (server client) quando si visualizza il contenuto di rete.
  • Android: richiede solo quando si visualizza contenuto dalla rete. Il contenuto locale non richiede autorizzazioni speciali.
  • iOS: non richiede autorizzazioni speciali.

Layout

A differenza della Xamarin.Forms maggior parte delle altre viste, richiede che e siano specificati quando sono contenuti in WebViewHeightRequestWidthRequest StackLayout o RelativeLayout. Se non si specificano tali proprietà, non verrà WebView eseguito il rendering di .

Gli esempi seguenti illustrano i layout che comportano il funzionamento e il rendering WebView di :

StackLayout con WidthRequest & HeightRequest:

<StackLayout>
    <Label Text="test" />
    <WebView Source="https://dotnet.microsoft.com/apps/xamarin"
        HeightRequest="1000"
        WidthRequest="1000" />
</StackLayout>

RelativeLayout con WidthRequest & HeightRequest:

<RelativeLayout>
    <Label Text="test"
        RelativeLayout.XConstraint= "{ConstraintExpression
                                      Type=Constant, Constant=10}"
        RelativeLayout.YConstraint= "{ConstraintExpression
                                      Type=Constant, Constant=20}" />
    <WebView Source="https://dotnet.microsoft.com/apps/xamarin"
        RelativeLayout.XConstraint="{ConstraintExpression Type=Constant,
                                     Constant=10}"
        RelativeLayout.YConstraint="{ConstraintExpression Type=Constant,
                                     Constant=50}"
        WidthRequest="1000" HeightRequest="1000" />
</RelativeLayout>

AbsoluteLayout senza WidthRequest HeightRequest:

<AbsoluteLayout>
    <Label Text="test" AbsoluteLayout.LayoutBounds="0,0,100,100" />
    <WebView Source="https://dotnet.microsoft.com/apps/xamarin"
      AbsoluteLayout.LayoutBounds="0,150,500,500" />
</AbsoluteLayout>

Griglia senza WidthRequest HeightRequest. Grid è uno dei pochi layout che non richiedono la specifica di altezze e larghezze richieste:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="100" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Label Text="test" Grid.Row="0" />
    <WebView Source="https://dotnet.microsoft.com/apps/xamarin" Grid.Row="1" />
</Grid>

Chiamata di JavaScript

WebView include la possibilità di richiamare una funzione JavaScript da C# e restituire qualsiasi risultato al codice C# chiamante. Questa operazione viene eseguita con il WebView.EvaluateJavaScriptAsync metodo , illustrato nell'esempio seguente WebView.EvaluateJavaScriptAsync

var numberEntry = new Entry { Text = "5" };
var resultLabel = new Label();
var webView = new WebView();
...

int number = int.Parse(numberEntry.Text);
string result = await webView.EvaluateJavaScriptAsync($"factorial({number})");
resultLabel.Text = $"Factorial of {number} is {result}.";

Il metodo valuta il codice JavaScript specificato come argomento e WebView.EvaluateJavaScriptAsync restituisce qualsiasi risultato come string . In questo esempio viene richiamata la funzione factorial JavaScript, che restituisce il fattoriale number di come risultato. Questa funzione JavaScript è definita nel file HTML locale caricato dall'oggetto ed WebView è illustrata nell'esempio seguente:

<html>
<body>
<script type="text/javascript">
function factorial(num) {
        if (num === 0 || num === 1)
            return 1;
        for (var i = num - 1; i >= 1; i--) {
            num *= i;
        }
        return num;
}
</script>
</body>
</html>

Cookie

I cookie possono essere impostati in WebView un oggetto , che vengono quindi inviati con la richiesta Web all'URL specificato. Questa operazione viene eseguita aggiungendo Cookie oggetti a un oggetto , che viene quindi impostato come valore della proprietà CookieContainerWebView.Cookies associabile. Il codice seguente illustra un esempio di questo:

using System.Net;
using Xamarin.Forms;
// ...

CookieContainer cookieContainer = new CookieContainer();
Uri uri = new Uri("https://dotnet.microsoft.com/apps/xamarin", UriKind.RelativeOrAbsolute);

Cookie cookie = new Cookie
{
    Name = "XamarinCookie",
    Expires = DateTime.Now.AddDays(1),
    Value = "My cookie",
    Domain = uri.Host,
    Path = "/"
};
cookieContainer.Add(uri, cookie);
webView.Cookies = cookieContainer;
webView.Source = new UrlWebViewSource { Url = uri.ToString() };

In questo esempio viene aggiunto un Cookie singolo oggetto all'oggetto CookieContainer , che viene quindi impostato come valore della proprietà WebView.Cookies . Quando invia WebView una richiesta Web all'URL specificato, il cookie viene inviato con la richiesta.

UiWebView Deprecation and App Store Rejection (ITMS-90809)

A partire da aprile 2020, Apple rifiuterà le app che usano ancora l'API deprecata. Anche se è passata a come impostazione predefinita, nei file binari è ancora presente un riferimento Xamarin.FormsWKWebView all'SDK Xamarin.Forms precedente. Il comportamento corrente del linker iOS non rimuove questo comportamento e, di conseguenza, l'API deprecata continuerà a essere referenziata dall'app quando si esegue l'invio al App Store.

Importante

Nella Xamarin.Forms versione 5.0 la WebViewRenderer classe è stata rimossa. Pertanto, Xamarin.Forms la versione 5.0 non contiene un riferimento al UIWebView controllo .

Per risolvere questo problema, è disponibile una versione di anteprima del linker. Per abilitare l'anteprima, è necessario fornire un argomento --optimize=experimental-xforms-product-type aggiuntivo al linker.

I prerequisiti per il funzionamento sono:

  • 4.5 o versione successiva. Xamarin.Forms La versione 4.6 o successiva è obbligatoria se l'app usa Material Visual.
  • Xamarin.iOS 13.10.0.17 o versione successiva. Controllare la versione di Xamarin.iOS in Visual Studio. Questa versione di Xamarin.iOS è inclusa in Visual Studio per Mac 8.4.1 e Visual Studio 16.4.3.
  • Rimuovere i riferimenti a . Il codice non deve avere riferimenti a UIWebView o a classi che usano UIWebView .

Per altre informazioni sul rilevamento e la rimozione di UIWebView riferimenti, vedere UIWebView.

Configurare il linker

Seguire questa procedura per il linker per rimuovere i UIWebView riferimenti:

  1. Aprire le proprietà del progetto iOS: fare clic con il pulsante destro del mouse sul progetto iOS e scegliere Proprietà.
  2. Passare alla sezione Compilazione iOS: selezionare la sezione Compilazione iOS.
  3. Aggiornare gli argomenti mtouch aggiuntivi: in Argomenti mtouch aggiuntivi aggiungere questo flag (oltre a qualsiasi valore che potrebbe essere già presente). Nota: questo flag funziona insieme al comportamento del linker impostato su Solo SDK o Collega tutto. Se, per qualsiasi motivo, vengono visualizzati errori durante l'impostazione del comportamento del linker su Tutti, è molto probabile che si tratta di un problema all'interno del codice dell'app o di una libreria di terze parti che non è sicura dal linker. Per altre informazioni sul linker, vedere Collegamento di app Xamarin.iOS.
  4. Aggiorna tutte le configurazioni di compilazione: usare gli elenchi Configurazione e Piattaforma nella parte superiore della finestra per aggiornare tutte le configurazioni di compilazione. La configurazione più importante da aggiornare è la configurazione release/iPhone, in quanto viene in genere usata per creare compilazioni per l App Store invio.

È possibile visualizzare la finestra con il nuovo flag in questo screenshot:

Impostazione del flag nella sezione Compilazione iOS

A questo punto, quando si crea una nuova compilazione (versione) e la si invia al App Store, non dovrebbero essere presenti avvisi sull'API deprecata.