Construindo aplicação Web com Flutter
Se você já leu o artigo Flutter: porque você deveria apostar nesta tecnologia, já tem um motivo para começar a aprender flutter, neste artigo abordarei em como você irá iniciar sua carreira com flutter para web.
Configurando o ambiente
Para você iniciar em flutter, o primeiro passo é fazer a instalação do nosso amigão. Flutter está disponível para as seis plataformas mais conhecidas Android, iOs, Web, Windows, macOS e Linux, neste exemplo só usaremos Web.
Flutter é muito fácil de instalar, basta você seguir o guia que está disponível aqui.
Recursos necessários:
Recursos necessários VSCode:
Certifique-se de estar com a versão ≥ 3.56.0 da extensão Flutter
Após baixado e instalado, o flutter ainda não está pronto para conseguirmos desenvolver para web com a versão estável, então iremos atualiza-lo para pegar a versão mais recente que inclui os toolkits necessários para desenvolvermos web.
Abra o terminal e digite:
flutter upgrade
Pronto, agora estamos pronto para desenvolvermos tanto mobile quanto web.
Criando o projeto
Abra o Visual Studio Code, em seguida Exibir -> Paleta de Comandos (Cntrl + Shift + P ou Command + Shift + P) e digite:
Flutter: New Web Project
Eu criei o projeto com o nome de “flutter_web_teste” mesmo, você pode dar o nome que preferir. Aguarde enquanto o flutter realiza o download de todas as diretivas e packages necessárias para a criação do projeto, esse processo pode demorar por ser a primeira vez.
Após executado o comando, você terá um projeto base e iremos codificar a partir dele. O projeto inicial possui o seguinte esqueleto de arquivos:
Para rodar na web, no canto final existe o padrão de dispositivo, selecione Chrome web ou Edge web
Veja ele executando o exemplo abaixo.
Códido Fonte do Exemplo acima.
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Primeira aplicação com Flutter', // title da página theme: ThemeData( primarySwatch: Colors.blue, ), // ignore: avoid_unnecessary_containers home: Container( child: const Center( child: CounterWidget(), ), )); } } class CounterWidget extends StatefulWidget { const CounterWidget({super.key}); @override // ignore: library_private_types_in_public_api _CounterWidgetState createState() => _CounterWidgetState(); } class _CounterWidgetState extends State<CounterWidget> { int _counter = 10; Future<void> _fimAlert(BuildContext context) { return showDialog<void>( context: context, builder: (BuildContext context) { return AlertDialog( title: const Text('Alerta'), content: const Text('O contador será reiniciado'), actions: <Widget>[ TextButton( child: const Text('Ok'), onPressed: () { setState(() { _counter = 10; }); Navigator.of(context).pop(); }, ), ], ); }, ); } @override Widget build(BuildContext context) { final ButtonStyle flatButtonStyle = TextButton.styleFrom( foregroundColor: Colors.amber, ); // ignore: avoid_unnecessary_containers return Container( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text( "$_counter", style: const TextStyle(color: Colors.grey, fontSize: 40.0), ), TextButton( style: flatButtonStyle, onPressed: () { setState(() { _counter--; if (_counter == 0) _fimAlert(context); }); }, child: const Text('Decrementar'), ) ], ), ); } }
Vamos ao To Do
Agora crie um novo arquivo na pasta lib com o nome de todo.dart
import 'package:flutter/material.dart'; class TodoPage extends StatefulWidget { @override _TodoPageState createState() => _TodoPageState(); } class _TodoPageState extends State<TodoPage> { //Controllers são usadas quando precisamos resgatar ou modificar uma propriedade de um widget final _textController = TextEditingController(); //Lista responsável por popular nosso ListView List _toDoList = []; //Caso o usuário remover uma tarefa, ela ficará em memória nesta variável por um tempo Map<String, dynamic>? _lastRemoved; int? _lastRemovedPos; void addToDo() { setState(() { Map<String, dynamic> newTodo = Map(); newTodo["title"] = _textController.text; newTodo["ok"] = false; _toDoList.add(newTodo); _textController.text = ''; }); } void _dismissToDo( DismissDirection direction, BuildContext context, int index) { setState(() { _lastRemoved = Map.from(_toDoList[index]); _lastRemovedPos = index; _toDoList.removeAt(index); final snack = SnackBar( content: Text('Tarefa "${_lastRemoved!["title"]}" removida!'), action: SnackBarAction( label: "Desfazer", onPressed: () { setState(() { _toDoList.insert(_lastRemovedPos!, _lastRemoved); }); }, ), duration: const Duration(seconds: 5), ); ScaffoldMessenger.of(context).showSnackBar(snack); }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('ToDo Flutter'), backgroundColor: Colors.purple, ), body: Column( children: <Widget>[ Container( padding: const EdgeInsets.fromLTRB(17.0, 1.0, 7.0, 1.0), child: Row( children: <Widget>[ Expanded( child: TextField( controller: _textController, decoration: const InputDecoration( labelText: 'Nova tarefa', labelStyle: TextStyle(color: Colors.grey)), )), ElevatedButton( style: ElevatedButton.styleFrom( foregroundColor: Colors.white,//change background color of button backgroundColor: Colors.indigo,//change text color of button ), onPressed: addToDo, child: const Text('Adicionar'), ), ], )), Expanded( flex: 2, child: ListView.builder( padding: const EdgeInsets.only(top: 10.0), itemCount: _toDoList.length, itemBuilder: itemBuilder)) ], )); } Widget itemBuilder(context, index) { //Widget responsável por permitir dismiss return Dismissible( key: Key(DateTime.now().millisecondsSinceEpoch.toString()), //A propriedade "background" representa o fundo da nossa tile, o fundo em si não possui ações //As ações estão no evento onDismissed background: Container( color: Colors.redAccent, child: const Align( alignment: Alignment(-0.9, 0.0), child: Icon(Icons.delete, color: Colors.white), ), ), direction: DismissDirection.startToEnd, child: CheckboxListTile( onChanged: (c) { setState(() { _toDoList[index]["ok"] = c; }); }, title: Text(_toDoList[index]["title"]), value: _toDoList[index]["ok"], secondary: CircleAvatar( child: Icon(_toDoList[index]["ok"] ? Icons.check : Icons.error), ), ), onDismissed: (direction) { _dismissToDo(direction, context, index); }, ); } }
Após altere seu arquivo main.dart para o código abaixo
import 'package:flutter/material.dart'; import 'package:flutter_web_teste/todo.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Primeira aplicação com Flutter', // title da página theme: ThemeData( primarySwatch: Colors.blue, ), // ignore: avoid_unnecessary_containers home: TodoPage() ); } }
Vamos agora executar o código, pressione F5 para vermos o resultado. Se você estiver seguindo o tutorial a risca o resultado é para estar como no video abaixo
Um outro video com Exclusão.
É isso ai pessoal, temos uma aplicação feita em flutter web totalmente usavel e de rápida criação. Em breve lançarei alguns tutoriais mais avançados para criar web applications reais para o mercado.