Condividi tramite


Xamarin.Forms WebView

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

Nel browser app

Contenuto

WebView supporta i tipi di contenuto seguenti:

  • Siti Web HTML e CSS: WebView offre supporto completo per i siti Web scritti con HTML e CSS, 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ò mostrare stringhe HTML dalla memoria.
  • File locali: WebView può presentare qualsiasi tipo di contenuto sopra incorporato nell'app.

Nota

WebView in Windows non supporta Silverlight, Flash o alcun controllo ActiveX, anche se sono supportati da Internet Explorer su tale piattaforma.

Siti Web

Per visualizzare un sito Web da Internet, impostare la WebViewproprietà di su Source un URL 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

Dalla versione 9, iOS consentirà all'applicazione di comunicare solo con i server che implementano la sicurezza consigliata per impostazione predefinita. I valori devono essere impostati in Info.plist per abilitare 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 NSExceptionDomains invece di disattivare completamente ATS usando NSAllowsArbitraryLoads. NSAllowsArbitraryLoads deve essere utilizzato solo in situazioni di emergenza estreme.

Di seguito viene illustrato come abilitare un dominio specifico (in questo caso xamarin.com) per ignorare i requisiti 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 abilitare solo alcuni domini per ignorare ATS, consentendo di usare siti attendibili sfruttando al tempo stesso la sicurezza aggiuntiva nei domini non attendibili. Di seguito viene illustrato il metodo meno sicuro per disabilitare 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 definito in modo dinamico 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;

WebView Visualizzazione di stringhe HTML

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

Nota

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

Contenuto HTML locale

WebView può visualizzare contenuto da HTML, CSS e JavaScript incorporato nell'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 devono essere personalizzati per ogni piattaforma, in quanto non tutte le piattaforme hanno gli stessi tipi di carattere.

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

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

WebView che visualizza contenuto locale

Anche se la prima pagina è stata caricata, non WebView ha alcuna conoscenza della provenienza 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 dove WebView trovare i file nel file system. A tale scopo, impostare la BaseUrl proprietà sull'oggetto HtmlWebViewSource utilizzato da WebView.

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

Per usare , definire innanzitutto un'interfaccia DependencyServiceche può 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 BaseUrl usando :DependencyService

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

Le implementazioni dell'interfaccia per ogni piattaforma devono quindi essere fornite.

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 l'oggetto 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, è anche possibile accedere ai file nella cartella Assets tramite il contesto Android corrente, esposto dalla MainActivity.Instance 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 piattaforma UWP (Universal Windows Platform) (UWP) inserire 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 tramite diversi metodi e proprietà che rende disponibili:

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

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

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

Usare i metodi e le proprietà di spostamento 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();
        }
    }
}

Ecco fatto!

Pulsanti di spostamento webView

Eventi

WebView genera gli eventi seguenti per rispondere alle modifiche apportate allo 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.

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

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

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

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

Se si prevede di usare pagine Web che richiedono 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;
}

In questo modo viene restituito l'output seguente (caricamento):

Screenshot che mostra WebView Navigating Event durante il caricamento.

Caricamento completato:

Screenshot che mostra WebView Navigating Event dopo il caricamento.

Ricaricamento del contenuto

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

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

Quando il Reload metodo viene richiamato, viene generato l'evento ReloadRequested , a indicare che è stata effettuata una richiesta 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 stato implementato in iOS dalla UIWebView classe . Tuttavia, molte di queste tecnologie non erano disponibili in questa implementazione. Pertanto, dalla Xamarin.Forms versione 4.4, viene Xamarin.FormsWebView implementato in iOS dalla WkWebView classe , che supporta l'esplorazione più veloce.

Nota

In iOS, ha WkWebViewRenderer un overload del costruttore che accetta un WkWebViewConfiguration argomento. In questo modo il renderer deve essere configurato alla 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 della 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 5.0 non contiene un riferimento al UIWebView controllo .

WebView in Android per impostazione predefinita è il più veloce del browser predefinito.

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

Autorizzazioni

Per WebView poter funzionare, è necessario assicurarsi che le autorizzazioni siano impostate per ogni piattaforma. Si noti che in alcune piattaforme WebView funziona in modalità di debug, ma non in caso di compilazione per il rilascio. Ciò è dovuto al fatto che alcune autorizzazioni, ad esempio quelle per l'accesso a Internet in Android, vengono impostate per impostazione predefinita da Visual Studio per Mac in modalità di debug.

  • UWP : richiede la funzionalità Internet (Client & Server) durante la visualizzazione del contenuto di rete.
  • Android : richiede INTERNET solo quando si visualizza il contenuto dalla rete. Il contenuto locale non richiede autorizzazioni speciali.
  • iOS : non richiede autorizzazioni speciali.

Layout

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

Gli esempi seguenti illustrano i layout che comportano il funzionamento, il rendering WebViewdi s:

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. Griglia è 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>

Richiamo 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 metodo 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 WebView.EvaluateJavaScriptAsync metodo valuta il codice JavaScript specificato come argomento e restituisce qualsiasi risultato come .string In questo esempio viene richiamata la factorial funzione JavaScript, che restituisce il fattoriale di number di conseguenza. Questa funzione JavaScript viene definita nel file HTML locale caricato WebView e illustrato 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 un WebViewoggetto , che vengono quindi inviati con la richiesta Web all'URL specificato. A tale scopo, aggiungere Cookie oggetti a un CookieContaineroggetto , che viene quindi impostato come valore della WebView.Cookies proprietà associabile. Nel codice seguente ne viene illustrato un esempio:

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 singolo Cookie oggetto CookieContainer , che viene quindi impostato come valore della WebView.Cookies proprietà . WebView Quando invia 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 UIWebView . Anche se Xamarin.Forms è passato a WKWebView come impostazione predefinita, esiste ancora un riferimento all'SDK precedente nei Xamarin.Forms file binari. Il comportamento del linker iOS corrente non rimuove questo comportamento e di conseguenza l'API deprecata UIWebView risulterà ancora a cui viene fatto riferimento dall'app quando invii all'App Store.

Importante

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

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

I prerequisiti per questo funzionamento sono:

  • Xamarin.Forms 4.5 o versione successiva. Xamarin.Forms La versione 4.6 o successiva è obbligatoria se l'app usa l'oggetto visivo materiale.
  • 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 UIWebView. Il codice non deve avere riferimenti a UIWebView o a classi che usano UIWebView.

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

Configurare il linker

Seguire questa procedura per il linker per rimuovere UIWebView i 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 Build iOS : selezionare la sezione Build iOS.
  3. Aggiornare gli argomenti mtouch aggiuntivi: negli argomenti mtouch aggiuntivi aggiungere questo flag --optimize=experimental-xforms-product-type (oltre a qualsiasi valore che potrebbe essere già presente in tale campo). 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, questo è probabilmente un problema all'interno del codice dell'app o una libreria di terze parti che non è sicura del linker. Per altre informazioni sul linker, vedere Collegamento di app Xamarin.iOS.
  4. Aggiornare 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 , poiché in genere viene usata per creare build per l'invio in App Store.

Nella schermata seguente è possibile visualizzare la finestra con il nuovo flag:

Impostazione del flag nella sezione Build iOS

Ora quando crei una nuova build (versione) e la invii all'App Store, non dovrebbero esserci avvisi sull'API deprecata.