DEV Community

Pedro Massango
Pedro Massango

Posted on • Updated on

O poder dos WebViews em Flutter

Primeiro artigo da série onde irei traduzir artigos sobre Flutter escritos originalmente em outros idiomas, para mais acessibilidade e suporte na comunidade de língua portuguesa. Artigo originalmente publicado por Emily Fortuna que nos falar sobre webViews e a importância do uso de chaves (Key).


Você quer escrever uma aplicação que pode mostrar uma página web sem ter que abrir o navegador do seu dispositivo móvel? Ou talvez você já tem um fluxo de pagamento seguro implementado em seu site e não querem voltar a implementar a funcionalidade de pagamento na sua aplicação móvel — o dinheiro pode ser um negócio complicado e não quer acabar acidentalmente enviando metade do pagamento ao Fundo salvou o Kraken. É só eu? Bem, de qualquer forma, a equipe de Flutter criou um plugin muito legal que permite que você incorporar em sua aplicação WebViews para tornar esta funcionalidade possível.

Me referia a funcionalidade de mostrar páginas web em aplicações Flutter…não reabilitando krakens.

WebViews Flutter são como qualquer outro widget

Incorporar o plugin do WebView no seu aplicativo é extremamente simples. É apenas um widget como qualquer outro: WebView(initialUrl: ‘https://flutter.io'). Você pode também activar ou desactivar o JavaScript no seu WebView com o parámetro javascriptMode. Por padrão, JavaScript é desactivado, para ativar ele você construiria um WebView como este:

WebView(
initialUrl: 'https://flutter.io',
javascriptMode: JavascriptMode.unrestricted,
)

Praticamente todas as informações que você quer saber sobre o seu WebView e também a capacidade de controlar o seu WebView acontecem através do… espera… WebViewController. Este controlador é retornado em um retorno de chamada quando o WebView é totalmente construído:

WebViewController _controller;
WebView(
initialUrl: 'https://flutter.io',
onWebViewCreated: (WebViewController webViewController) {
_controller = webViewController;
},
);
//...later on, probably in response to some event:
_controller.loadUrl('http://dartlang.org/'
);

O WebViewController é seu tíquete para modificar o WebView programaticamente pelo Flutter ou acessar propriedades como o URL atual que está sendo exibido. Para ver como tudo isso funciona na prática, eu escrevi um aplicativo simples de navegação na Wikipédia que permite que você marque as páginas para mais tarde, para que o teórico nunca esqueça o último artigo fascinante da Wikipedia na próxima vez em que você mesmo caindo em um Wiki do buraco de coelho.

A Wikipedia-exploring app written in Flutter using WebViews. You can favorite pages and save them for later viewing

O código completo deste navegador do Wiki-do-buraco-de-coelho pode ser encontrado neste repositório GitHub.

WebView é apenas como qualquer outro widget em Flutter e pode ser composto com outros widgets em camadas sobre ele. Note que o botão de favorito é apenas um FloatingActionButton que está pairando no topo do WebView, complete com o efeito de sombra que você esperaria com o botão. Além disso, quando o menu suspenso da barra de aplicativos é aberto, ele cobre parcialmente o WebView como qualquer outro widget abaixo do menu.

Se você olhar o código, poderá notar que Eu usei aclasse Completer e FutureBuilder frequentemente neste exemplo. Declarando a variável de instância _controller como um Completer é o mesmo que adicionar um placeholder para o WebViewController. Podemos verificar se temos o WebViewController em funcionamento chamando _controller.isCompleted (significando que ele está completo quando temos um WebViewController válido) ou usando um FutureBuilder com o _controller.future
Usando um FutureBuilder nos permite construir novos componentes de interface do usuário como o FloatingActionButton para adicionar favoritos somente depois de ter um WebViewController funcionando (caso contrário, o programa não teria como obter currentUrl ao salvar uma página favoritada).

Duas outras funcionalidades da WebViews pode ser um pouco complexo, então vamos olhar de perto neles na duas sessões seguinte.


WebViews também podem capturar gestos específicos

Uma vez que WebViews são widgets , eles pode participar do protocolo de desambiguação de gestos de Flutter (aka o Gesture Arena). Por padrão, um WebView responde somente a gestos se nenhum outro widget reivindicar isso. Mas você pode fazer o WebView reivindicar proativamente um gesto especificando gestureRecognizers.

Se o seu WebView estiver dentro de outro widget que responda a gestos, por exemplo, um ListView, talvez você queira especificar como seu aplicativo responde a gestos. Se o usuário arrastar o dedo pela tela, você deverá rolar o ListView ou o WebView? Se você deseja que os dois widgets sejam roláveis, o widget WebView pode “capturar” o gesto de arrastar para que ele role quando o usuário arrasta o WebView, mas rola o ListView de outra forma. Você pode especificar quais gestos são passados ​​para o widget WebView com oparametro gestureRecognizers. O parâmetro leva um conjunto de todos os GestureRecognizers que você deseja capturar. Não se assuste com esse objeto Factory — basicamente, é apenas um método de construção glorificado. Para capturar o evento de rolagem vertical, posso escrever isso:

WebView(
initialUrl: someUrl,
gestureRecognizers: Set()
..add(Factory<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer())),
)

Ou, escrito de outro jeito:

var verticalGestures = Factory<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer());
var gestureSet = Set.from([verticalGestures]);
return WebView(
initialUrl: someUrl,
gestureRecognizers: gestureSet,
);

Se você assistiu o Boring Flutter Development Show por completo, você deve ter nos visto desenvolver o Kraken News, quero dizer, o Hacker News Reader App.

versão mais recente do aplicativo Hacker News que estamos desenvolvendo em nosso YouTube.

Para mostrar a captura de gestos no contexto de um aplicativo, modifiquei o aplicativo Hacker News para mostrar parte da página Web como uma “pré-visualização”. Isso permite que o usuário percorra a página vinculada verticalmente para determinar se deseja abri-la em um página separada para uma leitura mais aprofundada.

Hacker News Reader app com visualizações WebView dos links. Os WebViews capturam o gesto de arrastar vertical para permitir a rolagem das visualizações.

O código do aplicativo Hacker News reader app pode ser encontrado neste repositório do GitHub. (talvez mostrar aqui o código do _buildItem).

PageView(children: [
WebView(initialUrl: urlOne),
WebView(initialUrl: urlTwo),
WebView(initialUrl: urlThree),
]));
WebViews em um PageView. O PageView controla o deslizamento horizontal e os WebViews podem rolar verticalmente sem nenhum trabalho extra de sua parte.

Seus WebViews podem precisar do parámetro key

Você provavelmente já viu esses parâmetros opcionais key espalhados em praticamente todos os construtores Widget na base de código Flutter. As chaves são necessárias se você tiver vários widgets com estado do mesmo tipo que são removidos, adicionados ou reordenados no seu aplicativo. Como se constata, WebView é um widget com estado (o estado incluindo a página atual e o histórico do navegador). Portanto, se você tiver vários WebViews no seu aplicativo, talvez seja necessário adicionar um parâmetro key .

Um exemplo é no aplicativo Hacker News! Veja o que acontece quando mudamos de tab e nossas WebViews não têm chaves:

Isso é o que acontece se você não usar as chaves em um aplicativo com estado. Quando mudamos para a tab “New Stories”, a pré-visualização errada errada é exibida.

Como você pode ver, quando mudamos de tab, o bloco “Interview with Alan Kay” é expandido, mas a webview ainda mostra a página da BBC sobre a Virgin Galactic! Isso é corrigido colocando uma chave no widget de coleção mais alto (neste caso o widget ExpansionTile):

Ufa! O uso de chaves resolve o problema mostrando um WebView diferente (e o site correto) para cada item no aplicativo do leitor

A explicação super-abreviada de por que as chaves resolvem isso é que quando Flutter alterna a lista de histórias para exibir, ele vê que cada conjunto de histórias é feito de itens ListView com ExpansionTile. O Flutter tem um algoritmo de comparação rápida para evitar redesenhar desnecessariamente a tela que verifica o tipo e a chave do widget. Sem uma chave, como os tipos de widget de cada lista são os mesmos, os itens sem estado (como títulos de links) são atualizados, mas os componentes com estado (como o estado expandido de ExpansionTile e o URL do site) não são redesenhados. Adicionar uma chave corrige esse problema. Para uma explicação mais detalhada, confira este vídeo em chaves:

Da mesma forma, se você usar WebViews no contexto de um widget Hero, você vai querer usar global key assim Flutter irá saber que as duas WebViews são actualmente as mesmas e não precisa renderizar novamente a segunda.

Algumas coisas restantes para ter em mente:

O plug-in do WebView está atualmente na versão Preview enquanto terminamos de adicionar melhorias. Isso significa que, se você quiser executar o plug-in webview no iOS, precisará adicionar a seguinte linha dentro do <dict> no seu ios/Runner/Info.plist: como descrito neste issue do GitHub.

Há atualmente também um problema conhecido com o teclado do Android, e a equipe Flutter está trabalhando em uma solução.

Há outro plug-in WebView baseado na comunidade, embora ele não tenha todas as funcionalidades do plug-in acima, pela equipe Flutter. Ele simplesmente exibe uma página da Web em uma visualização nativa e não está integrado ao restante da árvore de widgets Flutter. Portanto, essa versão não permite compor WebViews com outros widgets arbitrários. Usando o plugin webview_flutter descrito neste artigo evita esse problema.

Isso é tudo, pessoal! Vá em frente e adicione WebViews aos seus aplicativos Flutter. E dê amor a esses krakens também.


Top comments (2)

Collapse
 
paulorobert profile image
Paulo Roberto

A idéia foi legal, uma vez que poucos profissionais Brasileiros falam inglês com fluência (se comparado ao restante do mundo, é claro), mas pegar o texto e colocar no Google Translate, matou a pau, algumas coisas ficam imcompreensiveis e parece um dialeto do mestre Yoda.

De toda forma, valeu a pró-atividade!

Collapse
 
mellogod profile image
Rafael Mello

Olá Pedro, tenho uma dúvida.

Estou executando um app com webview que vai rodar num Android 7.1, sem acesso a Playstore. Vi que a versão do engine do webview está desatualizada (chromium 51) é possível utilizar uma versão mais atualizada da engine do webview sem precisar atualizar no Android?