Xamarin.Forms WebView

WebView é uma visualização para exibir conteúdo da Web e HTML no seu aplicativo:

No navegador de aplicativos

Sumário

WebView Suporta os seguintes tipos de conteúdo:

  • Sites HTML e CSS – O WebView tem suporte total para sites escritos usando HTML e CSS, incluindo suporte a JavaScript.
  • Documentos – Como o WebView é implementado usando componentes nativos em cada plataforma, o WebView é capaz de mostrar documentos nos formatos suportados pela plataforma subjacente.
  • Strings HTML – O WebView pode mostrar strings HTML da memória.
  • Arquivos locais – o WebView pode apresentar qualquer um dos tipos de conteúdo acima incorporados no aplicativo.

Observação

WebView no Windows não oferece suporte a Silverlight, Flash ou quaisquer controles ActiveX, mesmo que sejam suportados pelo Internet Explorer nessa plataforma.

Sites

Para exibir um site da Internet, defina a WebViewpropriedade do Source como uma URL de cadeia de caracteres:

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

Observação

Os URLs devem ser totalmente formados com o protocolo especificado (ou seja, deve ter "http://" ou "https://" anexado a ele).

iOS e ATS

Desde a versão 9, o iOS só permitirá que seu aplicativo se comunique com servidores que implementam a segurança de práticas recomendadas por padrão. Os valores devem ser definidos para Info.plist permitir a comunicação com servidores não seguros.

Observação

Se o seu aplicativo exigir uma conexão com um site não seguro, você deve sempre inserir o domínio como uma exceção usando NSExceptionDomains em vez de desativar completamente o ATS usando NSAllowsArbitraryLoads. NSAllowsArbitraryLoads só deve ser usado em situações extremas de emergência.

O seguinte demonstra como habilitar um domínio específico (neste caso, xamarin.com) para ignorar os requisitos do 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>

É uma prática recomendada permitir que apenas alguns domínios ignorem o ATS, permitindo que você use sites confiáveis enquanto se beneficia da segurança adicional em domínios não confiáveis. O seguinte demonstra o método menos seguro de desabilitar o ATS para o aplicativo:

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

Consulte Segurança de Transporte de Aplicativos para obter mais informações sobre esse novo recurso no iOS 9.

HTML Strings

Se você quiser apresentar uma string de HTML definida dinamicamente no código, precisará criar uma instância 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;

WebView exibindo string HTML

No código acima, @ é usado para marcar o HTML como um literal de cadeia de caracteres literal, o que significa que a maioria dos caracteres de escape são ignorados.

Observação

Pode ser necessário definir as WidthRequest propriedades e HeightRequest do WebView para ver o conteúdo HTML, dependendo do layout do qual é WebView filho. Por exemplo, isso é necessário em um StackLayout.

Conteúdo HTML local

O WebView pode exibir conteúdo de HTML, CSS e JavaScript incorporados ao aplicativo. Por exemplo:

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

Observe que as fontes especificadas no CSS acima precisarão ser personalizadas para cada plataforma, pois nem todas as plataformas têm as mesmas fontes.

Para exibir conteúdo local usando um WebView, você precisará abrir o arquivo HTML como qualquer outro e, em seguida, carregar o conteúdo como uma cadeia de caracteres na Html propriedade de um HtmlWebViewSource. Para obter mais informações sobre como abrir arquivos, consulte Trabalhando com arquivos.

As capturas de tela a seguir mostram o resultado da exibição de conteúdo local em cada plataforma:

WebView exibindo conteúdo local

Embora a primeira página tenha sido carregada, o WebView não tem conhecimento de onde veio o HTML. Isso é um problema ao lidar com páginas que fazem referência a recursos locais. Exemplos de quando isso pode acontecer incluem quando as páginas locais são vinculadas umas às outras, uma página usa um arquivo JavaScript separado ou uma página é vinculada a uma folha de estilo CSS.

Para resolver isso, você precisa informar onde WebView encontrar arquivos no sistema de arquivos. Faça isso definindo a BaseUrl HtmlWebViewSource propriedade no usado pelo WebView.

Como o sistema de arquivos em cada um dos sistemas operacionais é diferente, você precisa determinar essa URL em cada plataforma. Xamarin.Forms Expõe o DependencyService para resolver dependências em tempo de execução em cada plataforma.

Para usar o , primeiro defina uma interface que possa ser implementada DependencyServiceem cada plataforma:

public interface IBaseUrl { string Get(); }

Observe que, até que a interface seja implementada em cada plataforma, o aplicativo não será executado. No projeto comum, lembre-se de definir o uso do BaseUrl DependencyService:

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

As implementações da interface para cada plataforma devem ser fornecidas.

iOS

No iOS, o conteúdo da Web deve estar localizado no diretório raiz do projeto ou no diretório Resources com a ação de build BundleResource, conforme demonstrado abaixo:

O BaseUrl deve ser definido para o caminho do pacote principal:

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

Android

No Android, coloque HTML, CSS e imagens na pasta Assets com a ação de build AndroidAsset , conforme demonstrado abaixo:

No Android, o BaseUrl deve ser definido como "file:///android_asset/":

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

No Android, os arquivos na pasta Ativos também podem ser acessados por meio do contexto atual do MainActivity.Instance Android, que é exposto pela propriedade:

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

Plataforma Universal do Windows

Em projetos UWP (Plataforma Universal do Windows), coloque HTML, CSS e imagens na raiz do projeto com a ação de build definida como Content.

O BaseUrl deve ser definido como "ms-appx-web:///":

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

O WebView oferece suporte à navegação por meio de vários métodos e propriedades que ele disponibiliza:

  • GoForward() – se CanGoForward for verdadeiro, a chamada GoForward navega para a próxima página visitada.
  • GoBack() – se CanGoBack for verdadeiro, a chamada GoBack navegará até a última página visitada.
  • CanGoBacktrue se houver páginas para navegar de volta, false se o navegador estiver no URL inicial.
  • CanGoForwardtrue se o usuário navegou para trás e pode avançar para uma página que já foi visitada.

Dentro das páginas, WebView não suporta gestos multitoque. É importante garantir que o conteúdo seja otimizado para dispositivos móveis e apareça sem a necessidade de zoom.

É comum que os aplicativos mostrem um link em um WebView, em vez do navegador do dispositivo. Nessas situações, é útil permitir a navegação normal, mas quando o usuário retorna enquanto está no link inicial, o aplicativo deve retornar ao modo de exibição normal do aplicativo.

Use os métodos e propriedades de navegação internos para habilitar esse cenário.

Comece criando a página para a visualização do navegador:

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

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

É isso!

Botões de navegação do WebView

Eventos

O WebView gera os seguintes eventos para ajudá-lo a responder a alterações no estado:

  • Navigating – gerado quando o WebView começa a carregar uma nova página.
  • Navigated – evento gerado quando a página é carregada e a navegação é interrompida.
  • ReloadRequested – evento gerado quando uma solicitação é feita para recarregar o conteúdo atual.

O WebNavigatingEventArgs objeto que acompanha o Navigating evento tem quatro propriedades:

  • Cancel – indica se deve ou não cancelar a navegação.
  • NavigationEvent – o evento de navegação que foi gerado.
  • Source – o elemento que executou a navegação.
  • Url – o destino de navegação.

O WebNavigatedEventArgs objeto que acompanha o Navigated evento tem quatro propriedades:

  • NavigationEvent – o evento de navegação que foi gerado.
  • Result – descreve o resultado da navegação, usando um WebNavigationResult membro de enumeração. Os valores válidos são Cancel, Failure, Success e Timeout.
  • Source – o elemento que executou a navegação.
  • Url – o destino de navegação.

Se você prevê o uso de páginas da Web que demoram muito para carregar, considere usar os Navigating eventos and Navigated para implementar um indicador de status. Por exemplo:

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

Os dois manipuladores de eventos:

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

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

Isso resulta na seguinte saída (carregamento):

A captura de tela mostra o evento de navegação do WebView durante o carregamento.

Carregamento finalizado:

A captura de tela mostra o evento de navegação do WebView após o carregamento.

Recarregando conteúdo

WebView tem um Reload método que pode ser usado para recarregar o conteúdo atual:

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

Quando o método Reload é chamado, o evento ReloadRequested é acionado, indicando que uma solicitação foi feita para recarregar o conteúdo atual.

Desempenho

Navegadores populares adotam tecnologias como renderização acelerada por hardware e compilação JavaScript. Antes da Xamarin.Forms versão 4.4, o Xamarin.FormsWebView foi implementado no iOS pela UIWebView classe. No entanto, muitas dessas tecnologias não estavam disponíveis nesta implementação. Portanto, desde Xamarin.Forms a WkWebView versão 4.4, o Xamarin.FormsWebView é implementado no iOS pela classe, que suporta navegação mais rápida.

Observação

No iOS, o WkWebViewRenderer tem uma sobrecarga de construtor que aceita um WkWebViewConfiguration argumento. Isso permite que o renderizador seja configurado na criação.

Um aplicativo pode voltar a usar a classe iOS UIWebView para implementar o Xamarin.FormsWebView, por motivos de compatibilidade. Isso pode ser feito adicionando o seguinte código ao arquivo AssemblyInfo.cs no projeto da plataforma iOS para o aplicativo:

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

Observação

Na Xamarin.Forms versão 5.0, a WebViewRenderer classe foi removida. Portanto, Xamarin.Forms 5.0 não contém uma referência ao UIWebView controle.

WebView no Android, por padrão, é quase tão rápido quanto o navegador embutido.

O UWP WebView usa o mecanismo de renderização do Microsoft Edge. Os dispositivos desktop e tablet devem ter o mesmo desempenho que usar o próprio navegador Edge.

Permissões

Para WebView funcionar, você deve certificar-se de que as permissões estejam definidas para cada plataforma. Observe que, em algumas plataformas, WebView funcionará no modo de depuração, mas não quando criado para lançamento. Isso ocorre porque algumas permissões, como aquelas para acesso à Internet no Android, são definidas por padrão pelo Visual Studio para Mac quando no modo de depuração.

  • UWP – requer o recurso de Internet (Cliente e Servidor) ao exibir conteúdo de rede.
  • Android – requer INTERNET apenas ao exibir conteúdo da rede. O conteúdo local não requer permissões especiais.
  • iOS – não requer permissões especiais.

Layout

Ao contrário da maioria das outras Xamarin.Forms exibições, WebView requer isso HeightRequest e WidthRequest são especificadas quando contidas em StackLayout ou RelativeLayout. Se você não especificar essas propriedades, o não WebView será renderizado.

Os exemplos a seguir demonstram layouts que resultam em trabalho, renderizando WebViews:

StackLayout com WidthRequest e HeightRequest:

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

RelativeLayout com 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 sem 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>

Grade sem WidthRequest & HeightRequest. Grid é um dos poucos layouts que não requer a especificação de alturas e larguras solicitadas.:

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

Invocando JavaScript

WebView inclui a capacidade de invocar uma função JavaScript do C# e retornar qualquer resultado para o código C# de chamada. Isso é feito com o método 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}.";

O método WebView.EvaluateJavaScriptAsync avalia o JavaScript especificado como o argumento e retorna qualquer resultado como um string. Neste exemplo, a função JavaScript factorial é invocada, que retorna o fatorial de number como resultado. Essa função JavaScript é definida no arquivo HTML local que o WebView carrega e é mostrada no seguinte exemplo:

<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

Os cookies podem ser definidos em um WebView, que são enviados com a solicitação da web para o URL especificado. Isso é feito adicionando Cookie objetos a um CookieContainer, que é então definido como o valor da WebView.Cookies propriedade associável. O código a seguir mostra um exemplo disso:

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

Neste exemplo, um Cookie é adicionado ao objeto CookieContainer, que é definido como o valor da propriedade WebView.Cookies. Quando o WebView envia uma solicitação da Web para a URL especificada, o cookie é enviado com a solicitação.

Substituição do UIWebView e rejeição da App Store (ITMS-90809)

A partir de abril de 2020, a Apple rejeitará aplicativos que ainda usam a API obsoleta UIWebView . Embora Xamarin.Forms tenha mudado para WKWebView como padrão, ainda há uma referência ao SDK mais antigo nos Xamarin.Forms binários. O comportamento atual do vinculador do iOS não remove isso e, como resultado, a API obsoleta UIWebView ainda parecerá ser referenciada do seu aplicativo quando você enviar para a App Store.

Importante

Na Xamarin.Forms versão 5.0, a WebViewRenderer classe foi removida. Portanto, Xamarin.Forms 5.0 não contém uma referência ao UIWebView controle.

Uma versão prévia do vinculador está disponível para corrigir esse problema. Para habilitar a versão prévia, você precisará fornecer um argumento --optimize=experimental-xforms-product-type adicional para o vinculador.

Os pré-requisitos para que isso funcione são:

  • Xamarin.Forms 4.5 ou superior. Xamarin.Forms 4.6 ou superior é necessário se o aplicativo usar o Material Visual.
  • Xamarin.iOS 13.10.0.17 ou superior. Verifique sua versão do Xamarin.iOS no Visual Studio. Esta versão do Xamarin.iOS está incluída no Visual Studio para Mac 8.4.1 e no Visual Studio 16.4.3.
  • Remova as referências a UIWebView. Seu código não deve ter referências UIWebView ou classes que usem UIWebView.

Para obter mais informações sobre como detectar e remover UIWebView referências, consulte Substituição de UIWebView.

Configurar o vinculador

Siga estas etapas para que o vinculador remova UIWebView referências:

  1. Abra as propriedades do projeto iOS – Clique com o botão direito do mouse no projeto iOS e escolha Propriedades.
  2. Navegue até a seção iOS Build – Selecione a seção iOS Build .
  3. Atualize os argumentos adicionais do mtouch – nos argumentos adicionais do mtouch, adicione esse sinalizador --optimize=experimental-xforms-product-type (além de qualquer valor que já possa estar lá). Observação: esse sinalizador funciona em conjunto com o Comportamento do Vinculador definido como Somente SDK ou Vincular Tudo. Se, por qualquer motivo, você vir erros ao definir o Comportamento do Vinculador como Todos, isso provavelmente é um problema no código do aplicativo ou em uma biblioteca de terceiros que não é segura para o vinculador. Para obter mais informações sobre o vinculador, consulte Vinculando aplicativos Xamarin.iOS.
  4. Atualizar todas as configurações de compilação – Use as listas Configuração e Plataforma na parte superior da janela para atualizar todas as configurações de compilação. A configuração mais importante a ser atualizada é a configuração Release/iPhone , já que normalmente é usada para criar compilações para envio na App Store.

Você pode ver a janela com o novo sinalizador nesta captura de tela:

Definindo o sinalizador na seção Build do iOS

Agora, quando você cria uma nova compilação (versão) e a envia para a App Store, não deve haver avisos sobre a API obsoleta.