Xamarin.Forms Visualização do Web

Download Sample Baixe o exemplo

WebView é um modo de exibição para exibir conteúdo da Web e HTML em seu aplicativo:

In App Browser

Sumário

WebView suporta os seguintes tipos de conteúdo:

  • HTML & CSS websites – WebView tem suporte completo para sites escritos usando HTML & 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.
  • Cadeias de caracteres HTML – WebView pode mostrar cadeias de caracteres HTML da memória.
  • Arquivos locais – WebView pode apresentar qualquer um dos tipos de conteúdo acima incorporados no aplicativo.

Observação

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

Sites

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

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

Observação

As URLs devem ser totalmente formadas com o protocolo especificado (ou seja, devem ter "http://" ou "https://" anexados a ele).

iOS e ATS

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

Observação

Se seu aplicativo exigir uma conexão com um site não seguro, você sempre deverá inserir o domínio como uma exceção usando em vez de desativar completamente o ATS usando NSExceptionDomainsNSAllowsArbitraryLoadso . 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 Aplicativo para obter mais informações sobre esse novo recurso no iOS 9.

Cadeias de caracteres HTML

Se você quiser apresentar uma cadeia de caracteres de HTML definida dinamicamente no código, será necessário 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 Displaying HTML String

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 para ver o conteúdo HTML, dependendo do layout do WebView qual o WebView filho é filho. Por exemplo, isso é necessário em um StackLayoutarquivo .

Conteúdo HTML Local

O WebView pode exibir conteúdo de HTML, CSS e JavaScript incorporado no 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 , 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 HtmlWebViewSourceWebView. 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 Displaying Local Content

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

Para resolver isso, você precisa dizer onde WebView encontrar arquivos no sistema de arquivos. Faça isso definindo a BaseUrl propriedade no HtmlWebViewSource 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 pode 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, certifique-se de que você se lembre de definir o usando o BaseUrlDependencyService:

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

As implementações da interface para cada plataforma devem então 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 compilação 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 Ativos com a ação de compilação 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 Android, que é exposto pela MainActivity.Instance 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 da Plataforma Universal do Windows (UWP), coloque HTML, CSS e imagens na raiz do projeto com a ação de compilação definida como Conteúdo.

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 true, a chamada navega para a GoForward próxima página visitada.
  • GoBack() – se CanGoBack for true, a chamada GoBack navegará até a última página visitada.
  • CanGoBacktrue se houver páginas para as quais navegar de volta, false se o navegador estiver na URL inicial.
  • CanGoForwardtrue se o usuário tiver navegado para trás e puder avançar para uma página que já foi visitada.

Dentro de páginas, WebView não suporta gestos multitoque. É importante certificar-se de que o conteúdo é otimizado para dispositivos móveis e aparece sem a necessidade de zoom.

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

Use os métodos de navegação internos e as propriedades 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!

WebView Navigation Buttons

Eventos

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

  • Navigating – evento gerado quando o WebView começa a carregar uma nova página.
  • Navigated – evento gerado quando a página é carregada e a navegação foi 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 da 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 da navegação.

Se você prevê o uso de páginas da Web que levam muito tempo para carregar, considere usar os Navigating eventos e 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):

Screenshot shows WebView Navigating Event while loading.

Carregamento finalizado:

Screenshot shows WebView Navigating Event after loading.

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 é chamado, o evento é acionado, indicando que uma solicitação foi feita para recarregar o ReloadReloadRequested conteúdo atual.

Desempenho

Navegadores populares adotam tecnologias como renderização acelerada por hardware e compilação JavaScript. Antes da Xamarin.Forms 4.4, o Xamarin.FormsWebView era implementado no iOS pela UIWebView turma. No entanto, muitas dessas tecnologias não estavam disponíveis nessa 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, é tão rápido quanto o navegador integrado.

O WebView da UWP 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 funcionar WebView , você deve certificar-se de que as permissões estejam definidas para cada plataforma. Observe que em algumas plataformas, funcionará no modo de depuração, WebView mas não quando compilado para lançamento. Isso ocorre porque algumas permissões, como as 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 Internet (Cliente & 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 dos outros Xamarin.Forms modos de exibição, WebView requer isso HeightRequest e WidthRequest são especificados quando contidos em StackLayout ou RelativeLayout. Se você não especificar essas propriedades, o WebView não será renderizado.

Os exemplos a seguir demonstram layouts que resultam em renderização WebViewde trabalho:

StackLayout com WidthRequest & 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. A grade é um dos poucos layouts que não requer a especificação das 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 WebView.EvaluateJavaScriptAsync método, que é mostrado no exemplo a seguir do exemplo WebView:

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 WebView.EvaluateJavaScriptAsync método avalia o JavaScript especificado como o argumento e retorna qualquer resultado como um stringarquivo . Neste exemplo, a função JavaScript é invocada, que factorial retorna o fatorial de number como resultado. Essa função JavaScript é definida no arquivo HTML local que o WebView carrega e é mostrada no exemplo a seguir:

<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 configurados em um WebView, que são enviados com a solicitação da web para a URL especificada. Isso é feito adicionando Cookie objetos a um CookieContainer, que é definido como o valor da WebView.Cookies propriedade vinculá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 único Cookie é adicionado ao CookieContainer objeto, que é definido como o valor da WebView.Cookies propriedade. Quando o envia uma solicitação da Web para a URL especificada, o WebView 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 preterida 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 preterida ainda parecerá ser referenciada UIWebView 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 de visualização do vinculador está disponível para corrigir esse problema. Para habilitar a visualização, você precisará fornecer um argumento --optimize=experimental-xforms-product-type adicional ao vinculador.

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

  • Xamarin.Forms 4.5 ou superior. Xamarin.Forms A versão 4.6 ou superior é necessária se seu 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 Visual Studio 16.4.3.
  • Remover referências ao UIWebView. Seu código não deve ter referências ou UIWebView classes que façam uso do UIWebView.

Para obter mais informações sobre como detectar e remover UIWebView referências, consulte Substituição do 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 do iOS e escolha Propriedades.
  2. Navegue até a seção Compilação do iOS – Selecione a seção Compilação do iOS.
  3. Atualizar os argumentos mtouch adicionais – Nos argumentos mtouch adicionais, adicione esse sinalizador --optimize=experimental-xforms-product-type (além de qualquer valor que já esteja lá). Nota: 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 vinculadores. 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 ela normalmente é usada para criar compilações para envio da App Store.

Você pode ver a janela com a nova bandeira no lugar nesta captura de tela:

Setting the flag in the iOS Build section

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