Xamarin.Forms Visualização do Web
WebView
é um modo de exibição para exibir conteúdo da Web e HTML em seu aplicativo:
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 WebView
propriedade '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 NSExceptionDomains
em vez de desativar completamente o ATS usando NSAllowsArbitraryLoads
o . 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;
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 o WebView
filho é filho. Por exemplo, isso é necessário em um StackLayout
arquivo .
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 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:
Embora a primeira página tenha sido carregada, o WebView
não tem conhecimento de onde o 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 DependencyService
em 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 BaseUrl
DependencyService
:
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:///";
}
}
}
Navegação
O WebView oferece suporte à navegação por meio de vários métodos e propriedades que ele disponibiliza:
- GoForward() – se
CanGoForward
for true, a chamadaGoForward
navega para a próxima página visitada. - GoBack() – se
CanGoBack
for true, a chamadaGoBack
navegará até a última página visitada. - CanGoBack –
true
se houver páginas para as quais navegar de volta,false
se o navegador estiver na URL inicial. - CanGoForward –
true
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!
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 umWebNavigationResult
membro de enumeração. Os valores válidos sãoCancel
,Failure
,Success
eTimeout
.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):
Carregamento finalizado:
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 Reload
método é chamado, o ReloadRequested
evento é 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 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, WebView
funcionará no modo de depuração, 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 WebView
de 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 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 WebView.EvaluateJavaScriptAsync
método avalia o JavaScript especificado como o argumento e retorna qualquer resultado como um string
arquivo . 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 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 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 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 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 ouUIWebView
classes que façam uso doUIWebView
.
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:
- Abra as propriedades do projeto iOS – Clique com o botão direito do mouse no projeto do iOS e escolha Propriedades.
- Navegue até a seção Compilação do iOS – Selecione a seção Compilação do iOS.
- 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. - 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:
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.