Xamarin.Forms Webview

Ejemplo de descarga Descarga del ejemplo

WebView es una vista para mostrar contenido web y HTML en la aplicación:

En el explorador de aplicaciones

Contenido

WebView admite los siguientes tipos de contenido:

  • Sitios & web CSS HTML: WebView tiene compatibilidad completa con sitios web escritos con & CSS HTML, incluida la compatibilidad con JavaScript.
  • Documentos: dado que WebView se implementa mediante componentes nativos en cada plataforma, WebView es capaz de mostrar documentos en los formatos admitidos por la plataforma subyacente.
  • Cadenas HTML: WebView puede mostrar cadenas HTML desde la memoria.
  • Archivos locales: WebView puede presentar cualquiera de los tipos de contenido anteriores insertados en la aplicación.

Nota:

WebViewen Windows no admite Silverlight, Flash ni ningún control ActiveX, incluso si son compatibles con Internet Explorer en esa plataforma.

Websites

Para mostrar un sitio web desde Internet, establezca la WebView propiedad en una dirección URL de Source cadena:

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

Nota:

Las direcciones URL deben tener el formato completo con el protocolo especificado (es decir, debe tener anteponer "http://" o "https://").

iOS y ATS

Desde la versión 9, iOS solo permitirá que la aplicación se comunique con los servidores que implementan la seguridad de procedimientos recomendados de forma predeterminada. Los valores deben establecerse en Info.plist para habilitar la comunicación con servidores no seguros.

Nota:

Si la aplicación requiere una conexión a un sitio web no seguro, siempre debe escribir el dominio como una excepción mediante en lugar de desactivar NSExceptionDomains ATS completamente mediante NSAllowsArbitraryLoads . NSAllowsArbitraryLoads solo se debe usar en situaciones de emergencia extremas.

A continuación se muestra cómo habilitar un dominio específico (en este caso, xamarin.com) para omitir los requisitos de 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>

Es un procedimiento recomendado habilitar solo algunos dominios para omitir ATS, lo que le permite usar sitios de confianza mientras se beneficia de la seguridad adicional en dominios que no son de confianza. A continuación se muestra el método menos seguro para deshabilitar ATS para la aplicación:

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

Consulte Seguridad de transporte de aplicaciones para obtener más información sobre esta nueva característica en iOS 9.

Cadenas HTML

Si desea presentar una cadena de HTML definida dinámicamente en el código, deberá crear una instancia de 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;

Vista web que muestra cadena HTML

En el código anterior, se usa para marcar el código HTML como literal de cadena textual, lo que significa que la mayoría de los caracteres de @ escape se @omiten.

Nota:

Puede que sea necesario establecer las propiedades y de para ver el contenido HTML, en función del diseño del que WidthRequestHeightRequest sea un elemento WebViewWebView secundario. Por ejemplo, esto es necesario en StackLayout un .

Contenido HTML local

WebView puede mostrar contenido de HTML, CSS y JavaScript insertado dentro de la aplicación. Por ejemplo:

<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;
}

Tenga en cuenta que las fuentes especificadas en la CSS anterior deban personalizarse para cada plataforma, ya que no todas las plataformas tienen las mismas fuentes.

Para mostrar contenido local mediante , deberá abrir el archivo HTML como cualquier otro y, a continuación, cargar el contenido como una cadena en la WebViewHtml propiedad de HtmlWebViewSource . Para obtener más información sobre cómo abrir archivos, vea Trabajar con archivos.

En las capturas de pantalla siguientes se muestra el resultado de mostrar contenido local en cada plataforma:

Vista web que muestra contenido local

Aunque se ha cargado la primera página, WebView no tiene ningún conocimiento de de dónde provenía el CÓDIGO HTML. Esto es un problema al tratar con páginas que hacen referencia a recursos locales. Entre los ejemplos de cuándo puede ocurrir esto se incluyen cuando las páginas locales se vinculan entre sí, una página usa un archivo JavaScript independiente o una página se vincula a una hoja de estilos CSS.

Para solucionar este problema, debe saber WebView dónde encontrar los archivos en el sistema de archivos. Para ello, establece BaseUrl la propiedad en el utilizado por HtmlWebViewSourceWebView .

Dado que el sistema de archivos de cada uno de los sistemas operativos es diferente, debe determinar esa dirección URL en cada plataforma. Xamarin.Forms expone para resolver DependencyService dependencias en tiempo de ejecución en cada plataforma.

Para usar DependencyService , defina primero una interfaz que se pueda implementar en cada plataforma:

public interface IBaseUrl { string Get(); }

Tenga en cuenta que hasta que la interfaz se implemente en cada plataforma, la aplicación no se ejecutará. En el proyecto común, asegúrese de que no olvide establecer mediante BaseUrlDependencyService :

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

A continuación, se deben proporcionar implementaciones de la interfaz para cada plataforma.

iOS

En iOS, el contenido web debe estar ubicado en el directorio raíz del proyecto o en el directorio Resources con la acción de compilación BundleResource, como se muestra a continuación:

Debe BaseUrl establecerse en la ruta de acceso del paquete principal:

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

Android

En Android, coloque HTML, CSS e imágenes en la carpeta Assets con la acción de compilación AndroidAsset, como se muestra a continuación:

En Android, BaseUrl debe establecerse en "file:///android_asset/" :

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

En Android, también se puede acceder a los archivos de la carpeta Assets a través del contexto actual de Android, que se expone mediante la propiedad :

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

Plataforma universal de Windows

En los proyectos Windows plataforma universal (UWP), coloque HTML, CSS e imágenes en la raíz del proyecto con la acción de compilación establecida en Contenido.

Debe BaseUrl establecerse en "ms-appx-web:///" :

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

WebView admite la navegación a través de varios métodos y propiedades que pone a disposición:

  • GoForward(): si es true, la llamada GoForward a navega hacia delante hasta la siguiente página visitada.
  • GoBack(): si es true, la llamada a GoBack navegará a la última página visitada.
  • CanGoBack: si hay páginas a las que volver, false si el explorador está en la dirección URL inicial.
  • CanGoForward: si el usuario ha navegado hacia atrás y puede avanzar a una página que ya se ha visitado.

Dentro de las WebView páginas, no admite gestos multi táctiles. Es importante asegurarse de que el contenido está optimizado para dispositivos móviles y aparece sin necesidad de zoom.

Es habitual que las aplicaciones muestren un vínculo dentro de WebView un , en lugar del explorador del dispositivo. En esas situaciones, resulta útil permitir la navegación normal, pero cuando el usuario vuelve a encontrarse en el vínculo inicial, la aplicación debe volver a la vista de la aplicación normal.

Use las propiedades y los métodos de navegación integrados para habilitar este escenario.

Empiece por crear la página para la vista del explorador:

<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>

En el código subyacente:

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();
        }
    }
}

Ya está.

Botones de navegación de WebView

Events

WebView genera los siguientes eventos para ayudarle a responder a los cambios de estado:

  • Navigating : evento que se genera cuando WebView comienza a cargar una página nueva.
  • Navigated : evento que se genera cuando se carga la página y se detiene la navegación.
  • ReloadRequested : evento que se genera cuando se realiza una solicitud para volver a cargar el contenido actual.

El WebNavigatingEventArgs objeto que acompaña al evento tiene cuatro Navigating propiedades:

  • Cancel : indica si se debe cancelar o no la navegación.
  • NavigationEvent : el evento de navegación que se ha producido.
  • Source : el elemento que realizó la navegación.
  • Url : el destino de navegación.

El WebNavigatedEventArgs objeto que acompaña al evento tiene cuatro Navigated propiedades:

  • NavigationEvent : el evento de navegación que se ha producido.
  • Result : describe el resultado de la navegación, utilizando un miembro WebNavigationResult de enumeración. Los valores válidos son Cancel, Failure, Success y Timeout.
  • Source : el elemento que realizó la navegación.
  • Url : el destino de navegación.

Si prevé usar páginas web que llevan mucho tiempo en cargarse, considere la posibilidad de usar los eventos Navigating y para implementar un indicador de Navigated estado. Por ejemplo:

<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>

Los dos controladores de eventos:

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

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

Esto da como resultado la siguiente salida (carga):

Captura de pantalla que muestra el evento de navegación de WebView durante la carga.

Carga finalizada:

Captura de pantalla que muestra webView Navigating Event después de la carga.

Recarga de contenido

WebView tiene un Reload método que se puede usar para volver a cargar el contenido actual:

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

Cuando se invoca el método, se desencadena el evento , lo que indica que se ha realizado una solicitud Reload para volver a cargar el contenido ReloadRequested actual.

Rendimiento

Los exploradores web populares adoptan tecnologías como la representación acelerada por hardware y la compilación de JavaScript. Antes de Xamarin.Forms la versión 4.4, la clase implementó en Xamarin.FormsWebViewUIWebView iOS. Sin embargo, muchas de estas tecnologías no estaban disponibles en esta implementación. Por lo tanto, desde la versión 4.4, la clase implementa en iOS, lo que admite Xamarin.FormsXamarin.FormsWebView una exploración WkWebView más rápida.

Nota:

En iOS, WkWebViewRenderer tiene una sobrecarga de constructor que acepta un argumento WkWebViewConfiguration . Esto permite configurar el representador durante la creación.

Una aplicación puede volver a usar la clase iOS UIWebView para implementar , por motivos de Xamarin.FormsWebView compatibilidad. Esto se puede lograr agregando el código siguiente al archivo AssemblyInfo.cs en el proyecto de plataforma iOS para la aplicación:

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

Nota:

En Xamarin.Forms la versión 5.0, se WebViewRenderer ha quitado la clase . Por lo Xamarin.Forms tanto, 5.0 no contiene una referencia al UIWebView control .

WebView en Android de forma predeterminada es tan rápido como el explorador integrado.

La vista web de UWP usa el Microsoft Edge de representación. Los dispositivos de escritorio y tableta deben ver el mismo rendimiento que el uso del propio explorador Edge.

Permisos

Para que funcione, debe asegurarse de que los permisos están WebView establecidos para cada plataforma. Tenga en cuenta que, en algunas plataformas, WebView funcionará en modo de depuración, pero no cuando se compila para la versión. Esto se debe a que algunos permisos, como los de acceso a Internet en Android, se establecen de forma predeterminada Visual Studio para Mac en modo de depuración.

  • UWP: requiere la funcionalidad Internet (servidor cliente) al mostrar contenido de red.
  • Android: solo requiere cuando se muestra contenido de la red. El contenido local no requiere permisos especiales.
  • iOS: no requiere permisos especiales.

Diseño

A diferencia de la mayoría de las demás vistas, requiere que Xamarin.FormsWebView y se HeightRequestWidthRequest especifiquen cuando se encuentran en StackLayout o RelativeLayout. Si no especifica esas propiedades, no WebView se representará.

En los ejemplos siguientes se muestran diseños que dan lugar a funciones y WebView representaciones de :

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 sin 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>

Cuadrícula sin WidthRequest HeightRequest. Grid es uno de los pocos diseños que no requieren especificar los altos y anchos solicitados:

<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>

Invocación de JavaScript

WebView incluye la capacidad de invocar una función de JavaScript desde C# y devolver cualquier resultado al código de C# que realiza la llamada. Esto se logra con el WebView.EvaluateJavaScriptAsync método , que se muestra en el ejemplo siguiente del ejemplo 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}.";

El método evalúa el JavaScript especificado como argumento y WebView.EvaluateJavaScriptAsync devuelve cualquier resultado como string . En este ejemplo, se factorial invoca la función de JavaScript, que devuelve el factorial de como number resultado. Esta función de JavaScript se define en el archivo HTML local que carga y WebView se muestra en el ejemplo siguiente:

<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>

Cookies

Las cookies se pueden establecer en WebView , que luego se envían con la solicitud web a la dirección URL especificada. Esto se logra mediante la adición de objetos a , que luego Cookie se establece como el valor de la propiedad CookieContainerWebView.Cookies enlazable. El código siguiente muestra un ejemplo de esto:

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() };

En este ejemplo, se agrega un único al objeto , que luego se Cookie establece como el valor de la propiedad CookieContainerWebView.Cookies . Cuando envía WebView una solicitud web a la dirección URL especificada, la cookie se envía con la solicitud.

Desuso y rechazo App Store UIWebView (ITMS-90809)

A partir de abril de 2020, Apple rechazará las aplicaciones que siguen utilizando la API en desuso. Aunque ha cambiado a como valor predeterminado, todavía hay una referencia Xamarin.Forms al SDK anterior en los archivos WKWebViewXamarin.Forms binarios. El comportamiento actual del vinculador de iOS no quita esto y, como resultado, la API en desuso seguirá apareciendo como referencia desde la aplicación cuando se envíe a la App Store.

Importante

En Xamarin.Forms la versión 5.0, se WebViewRenderer ha quitado la clase . Por lo Xamarin.Forms tanto, 5.0 no contiene una referencia al UIWebView control .

Hay disponible una versión preliminar del vinculador para corregir este problema. Para habilitar la versión preliminar, deberá proporcionar un argumento adicional --optimize=experimental-xforms-product-type al vinculador.

Los requisitos previos para que funcionen son:

  • 4.5 o superior. Xamarin.Forms Se requiere la versión 4.6 o posterior si la aplicación usa Material Visual.
  • Xamarin.iOS 13.10.0.17 o superior. Compruebe la versión de Xamarin.iOS en Visual Studio. Esta versión de Xamarin.iOS se incluye con Visual Studio para Mac 8.4.1 y Visual Studio 16.4.3.
  • Quite las referencias a . El código no debe tener ninguna referencia a UIWebView ni a ninguna clase que use UIWebView .

Para obtener más información sobre cómo detectar y quitar UIWebView referencias, vea UIWebView.

Configuración del vinculador

Siga estos pasos para que el vinculador quite UIWebView referencias:

  1. Abra las propiedades del proyecto de iOS: haga clic con el botón derecho en el proyecto de iOS y elija Propiedades.
  2. Vaya a la sección Compilación de iOS: seleccione la sección Compilación de iOS.
  3. Actualizar los argumentos mtouch adicionales: en los argumentos mtouch adicionales, agregue esta marca (además de cualquier valor que ya esté ahí). Nota: Esta marca funciona junto con el comportamiento del vinculador establecido en Solo SDK o Vincular todo. Si, por cualquier motivo, ve errores al establecer el comportamiento del vinculador en Todo, lo más probable es que se trata de un problema en el código de la aplicación o en una biblioteca de terceros que no es segura para el vinculador. Para obtener más información sobre el vinculador, vea Vinculación de aplicaciones de Xamarin.iOS.
  4. Actualizar todas las configuraciones de compilación: use las listas Configuración y Plataforma de la parte superior de la ventana para actualizar todas las configuraciones de compilación. La configuración más importante que se va a actualizar es la configuración release/iPhone, ya que normalmente se usa para crear compilaciones para App Store envío.

Puede ver la ventana con la nueva marca en su lugar en esta captura de pantalla:

Establecimiento de la marca en la sección Compilación de iOS

Ahora, cuando cree una nueva compilación (versión) y la envíe al App Store, no debería haber ninguna advertencia sobre la API en desuso.