Referência rápida de Flutter


Índice

1- Sobre o Flutter

Flutter é um kit de desenvolvimento, de código aberto, criado pelo Google, que permite a criação de aplicativos compilados nativamente para Android e IOS. Você escreve um único código e o aplicativo roda em ambas plataformas.

A linguagem de programação utilizada no Flutter é o Dart, uma linguagem de script voltada à web desenvolvida pela Google.

Para mais informações sobre o Dart acesse: Referência Dart


2- Referências

Documentação oficial: https://flutter.dev/docs


3- Instalação

A boa notícia é que você não precisa instalar nada para rodar HTML, ele já roda no seu browser, seja ele Chrome, Firefox, Edge, Safari ou similares.

Guia de instalação no windows: https://flutter.dev/docs/get-started/install/windows

1- Instalar o Android Studio

2- Baixar o zip do Flutter e descompactar Baixar o zip no site: https://flutter.dev/docs/get-started/install/windows e descompactar o pacote em uma pasta do seu computador, por exemplo: C:\flutter Não é recomendado instalar em uma pasta com privilégios elevados, como c:\Program files

3- Adicionar o caminho do flutter e do Android Studio no path

4- Instalar o Android Command Line

5- Aceitar as licenças do Android

Execute o comando:

$ flutter doctor --android-licenses

6- Executar o Flutter doctor

$ flutter doctor

Se houverem pendências de instalação, elas serão listadas. Se tudo estiver ok será exibido algo como:

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 2.5.3, on Microsoft Windows [Version 10.0.22000.348], locale pt-BR)
[√] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[√] Chrome - develop for the web
[√] Android Studio (version 2020.3)
[√] VS Code (version 1.62.3)
[√] Connected device (2 available)
• No issues found!

7- Configure um emulador do Android

Abra o Android Studio, e na página Welcome, clique em “More Actions” e então em “AVD Manager”

Então escolha a opção: Create Virtual Device…


4- IDEs

Uma ótima IDE para escrever aplicativos Flutter é o VSCode.

O VSCode é um editor FREE, rápido, leve e com uma infinidade de extensões para diferentes linguagens de programação, o que faz com que ele seja uma ótima opção para diferentes usos, vale destacar também que ele ganhou com folga a primeira posição da pesquisa anual do Stack Overflow de 2021 (link) como a IDE mais utilizada por programadores.

https://code.visualstudio.com/download

https://flutter.dev/docs/get-started/editor?tab=vscode

Dicas:

CTRL+SHIFT+P / “Dart: Use Recommended Settings”

CTRL+SHIFT+P / “Preferences: Open Workspace Settings (JSON)”

{
    "dart.lineLength": 100
}

CTRL+SHIFT+P / “Preferences: Open Settings (JSON)”

alterar “editor.rulers” e incluir “editor.codeActionsOnSave”

"[dart]": {
		"editor.formatOnSave": true,
		"editor.formatOnType": true,
		"editor.rulers": [
				100
		],
		"editor.selectionHighlight": false,
		"editor.suggest.snippetsPreventQuickSuggestions": false,
		"editor.suggestSelection": "first",
		"editor.tabCompletion": "onlySnippets",
		"editor.wordBasedSuggestions": false,
		"editor.codeActionsOnSave": {
				"source.fixAll": true
		}
},

Referência VSCode


5- Hello World

Aplicativo Hello World

Vá no Android Studio e inicie o emulador (Menu: Tools / AVD Manager / Create Virtual Device…)

Abra um prompt de comando e navegue até a pasta onde deseja criar o seu app, por exemplo:

mkdir c:\dev
cd c:\dev

Para criar o app, execute:

$ flutter create helloapp
$ cd helloapp

NOTA: Na primeira vez que você criar um app irá demorar mais, porque os pacotes serão baixados, nos próximos apps o processo será mais rápido

Então, para abrir o VSCode na pasta atual, execute:

$ code .

Quando o editor for carregado, será perguntado se você confia na origem do código, clique no botão “Yes, I trust”

Abra o arquivo “main.dart” na pasta “lib”, então substitua o conteúdo dele por:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Hello App')
        ),
        body: Text('Hello World!')
      )
    );
  }
}

Inicie o emulador do Android (Android Studio > AVD)

então inicie a aplicação no VSCode utilizando o menu: Run / Start Debugging, ou pressionando F5.

É possível executar a aplicação utilizando o terminal também, assim:

Abra um terminal no VSCode, menu: Terminal > New Terminal E então execute:

$ flutter run

Depois que a aplicação for iniciada, digite “r” para iniciar o “Hot reload”, assim, a cada modificação realizada o aplicativo será automaticamente atualizado.


6- Dart

A linguagem utilizada no Flutter é o Dart.

Para informações sobre a linguagem consulte: Referência Dart


7- Criando um app

//TODO: Complementar


8- Packages / Libs

Utilizando packages

Adicionando um package

O jeito mais fácil de adicionar um package é executando o comando “dart pub add [package]” ele vai automaticamente adicionar no arquivo “pubspec.yaml” a referência para o pacote

Por exemplo executando:

$ dart pub add json_serializable

No arquivo “pubspec.yaml” será adicionado:

dependencies:
  json_serializable: ^6.0.0

Para incluir essa pacote manualmente é necessário:

1- Adicionar a dependência no arquivo “pubspec.yaml”, por exemplo:

dependencies:
  json_serializable: ^6.0.0

2- Atualizar o aplicativo com os pacotes adicionados, executando:

$ flutter pub get

Atualizando os pacotes instalados

Para atualizar a versão de todos os pacotes, execute:

$ flutter packages upgrade

Se houverem packages que não foi possível atualizar será exibido um erro como:

x package is discontinued.
x packages have newer versions incompatible with dependency constraints.

Para verificar os pacotes com problemas de atualização, execute:

$ flutter pub outdated

Serialização JSON (lib json_serializable)

Referência: https://flutter.dev/docs/development/data-and-backend/json

O Flutter não possui equivalente ao Json.Net ou Newntonsoft do .NET para serialização e deserialização JSON porque para construir algo do tipo é necessário utilizar Reflection, que não está disponível no Flutter.

Sem a utilização de Reflection, existem duas forma de serialização no Flutter:

1- Manualmente

Na serialização manual é necessário mapear cada campo do json para um campo da classe, por exemplo:

class Album {
  final int id;
  final String title;

  Album({
    required this.id,
    required this.title,
  });

  factory Album.fromJson(Map<String, dynamic> json) {
    return Album(
      id: json['id'],
      title: json['title'],
    );
  }
}

string json = "{\"id\":1, \"title\":"Metallica Black album"}"
Map<String, dynamic> jsonMap = jsonDecode(json);
Album album = Album.fromJson(jsonMap);

Isso funciona para projetos pequenos, mas será bem difícil fazer isso manualmente para projetos grandes sem cometer erros.

2- Usando um gerador de código (recomendado)

A lib json_serializable é um exemplo de lib que faz a geração de código automaticamente

Referência oficial: https://pub.dev/packages/json_serializable

Para instalar, utilize:

$ dart pub add json_serializable

Se não tiver essas dependências, também é necessário adicionar:

$ dart pub add build_runner --dev
$ dart pub add json_annotation

A classe que será serializada (album.dart) fica assim:

import 'package:json_annotation/json_annotation.dart';

part 'album.g.dart';

class Album {
  final int id;
  final String title;

  Album({
    required this.id,
    required this.title,
  });

  factory UserApi.fromJson(Map<String, dynamic> json) => _$AlbumFromJson(json);
  Map<String, dynamic> toJson() => _$AlbumFromJson(this);
}

Para gerar os arquivos, execute:

$ flutter pub run build_runner build

Na classe (album.dart) é referenciado um arquivo parcial (part ‘album.g.dart’) esse arquivo será gerado automaticamente, quando o comando “build_runner build” for executado. Nesse arquivo estará implementado o método: _$AlbumFromJson com o mapeamento dos campos do JSON para os campos da classe.

Se ocorrer o seguinte erro:

pub finished with exit code 78

tente rodar:

$ flutter packages pub run build_runner build --delete-conflicting-outputs

O método toJson() retorna um tipo Map<String, dynamic> para converter esse mapa em uma string JSON utilize:

var album = Album(1, '');
String json = jsonEncode(album.toJson());

Native Splash Screen (lib flutter_native_splash)

Documentação oficial https://pub.dev/packages/flutter_native_splash

Vídeo, como utilizar: https://www.youtube.com/watch?v=8ME8Czqc-Oc

Para instalar o pacote, execute:

$ flutter pub add flutter_native_splash

e então adicione as configurações no arquivo “pubspec.yaml”, por exemplo:

flutter_native_splash:
  color: "#ffffff"
  image: assets/meu-logo.png
  android: true
  ios: true

Depois execute:

$ flutter clean; flutter pub get; flutter pub run flutter_native_splash:create

NOTA: No Linux ou no MAC o comando é assim:

$ flutter clean && flutter pub get && flutter pub run flutter_native_splash:create

ou você pode rodar cada comando indidivualmente.

ícones do app (launcher_icon)

Documentação oficial: https://pub.dev/packages/flutter_launcher_icons

Para instalar o pacote, execute:

$ flutter pub add flutter_launcher_icons

No arquivo pubspec.yaml adicione:

dev_dependencies:
  flutter_launcher_icons: "^0.9.2"

flutter_icons:
  android: "launcher_icon"
  ios: true
  image_path: "assets/icon/icon.png"

Em “image_path” informar o caminho para a imagem que deve ser utilizada como ícone do app

Então execute:

flutter pub get
flutter pub run flutter_launcher_icons:main

Executar chamada HTTP para uma API

Referência: https://flutter.dev/docs/cookbook/networking/fetch-data

Para instalar o pacote HTTP execute:

$ flutter pub add http

Isso irá adicionar a dependência abaixo no arquivo pubspec.yaml:

dependencies:
  http: ^0.13.4

No código adicionar o import:

import 'package:http/http.dart' as http;

Obter número da versão e do pacote

Referência https://pub.dev/packages/package_info_plus

Para instalar o pacote execute:

$ flutter pub add package_info_plus

Utilização:

import 'package:package_info_plus/package_info_plus.dart';

PackageInfo packageInfo = await PackageInfo.fromPlatform();

String appName = packageInfo.appName;
String packageName = packageInfo.packageName;
String version = packageInfo.version;
String buildNumber = packageInfo.buildNumber;

NOTA: O número da versão do app, fica na variável “version” do arquivo pubspec.yaml

Log

Referência: https://pub.dev/packages/logger

Para instalar o pacote execute:

$ flutter pub add logger

Utilização:

var logger = Logger();
logger.d("Log esta funcionando!");

Log levels:

logger.v("Verbose log");
logger.d("Debug log");
logger.i("Info log");
logger.w("Warning log");
logger.e("Error log");
logger.wtf("What a terrible failure log");

cached_network_image - Exibir imagem a partir da url

Uma boa opção é utilizar o plugin **cached_network_image**

Página oficial do plugin:
<a href="https://pub.dev/packages/cached_network_image" target="_blank" rel="nofollow">https://pub.dev/packages/cached_network_image</a>

Adicionar o plugin:

	flutter pub add cached_network_image

Importar no widget:

	import 'package:cached_network_image/cached_network_image.dart';

Exemplos de uso:

	CachedNetworkImage(
		imageUrl: 'https://picsum.photos/id/474/200/200',
	)

	CachedNetworkImage(
		imageUrl: 'https://picsum.photos/id/474/200/200',
		width: 200.0,
		height: 200.0,
		httpHeaders: {'authorization': 'bearer xxxxxx'},
	)

Abrir uma url no navegador padrão

O pacote url_launcher permite abrir uma url usando o navegador do celular

https://pub.dev/packages/url_launcher

Instalar o pacote:

$ flutter pub add url_launcher

No widget importar:

import 'package:url_launcher/url_launcher.dart';

Adicionar a entrada abaixo no arquivo AndroidManifest.xml (dentro do nó: manifest > application > activity):

<intent-filter>
	<action android:name="android.intent.action.VIEW" />
	<data android:scheme="https" />
</intent-filter>

Ela configura o Android para aceitar a abertura de urls https, se for utilizar outro tipo de url, como e-mail, é necessário adicionar outra entrada. Para mais detalhes consulte a documentação do package: https://pub.dev/packages/url_launcher

E utilizar:

_launchURL() async {
  const url = 'https://flutter.io';
	if (!await launch(_url)) {
		throw 'Could not launch $_url';
	}
}

Firebase

Documentação oficial: https://firebase.flutter.dev/docs/overview

Tutorial: https://firebase.google.com/codelabs/firebase-get-to-know-flutter

Tutorial Flutter - Configuração do Firebase: https://firebase.flutter.dev/docs/overview/

Tutorial Flutter - Firebase Messaging: https://firebase.flutter.dev/docs/messaging/overview

Projeto do Firebase

Primeiramente, crie um projeto do Firebase, para isso, acesse: https://console.firebase.google.com/

Instalar o Node.js

Se não tiver o NodeJs instalado, baixar e instalar: https://nodejs.org/en/download/

Para confirmar a instalação, abra um novo prompt de comando e digite:

node --version

Instalar do Firebase CLI

As instruções de instalação do Firebase CLI estão em: https://firebase.google.com/docs/cli

O jeito mais fácil de instalar é usando o npm, digite o seguinte no prompt:

npm install -g firebase-tools

Executar login no Firebase CLI

Ainda no prompt de comando, execute:

firebase login

Será aberto o browser para você realizar o login na sua conta do Firebase.

Você pode listar os projetos utilizando:

firebase projects:list

Instalação do plugin

Para instalar o plugin, navegue até a pasta do projeto, por exemplo:

cd c:\projetos\meu-app

e então execute o comando para instalar o plugin:

flutter pub add firebase_core

E então o comando:

dart pub global activate flutterfire_cli

Pode ser que esse comando solicite que você inclua uma variável de ambiente no windows, se for o caso, será exibida a seguinte mensagem:

Warning: Pub installs executables into C:\Users\educo\AppData\Local\Pub\Cache\bin, which is not on your path.
You can fix that by adding that directory to your system's "Path" environment variable.
A web search for "configure windows path" will show you how.

Nesse caso, inclua esse caminho no PATH do Windows. (Iniciar / Environment variables / [Environment Variables…] / System variable / PATH / [Edit] / [NEW]) Então, feche o prompt e abra outro para que o comando path esteja disponível

Para verificar a instalação execute:

flutterfire --version

Configuração do plugin

Para configurar o plugin execute:

flutterfire configure

Será pedido para selecionar o nome do projeto (usando as setas para cima e para baixo do teclado), selecione o nome do projeto criado no firebase console e pressione ENTER. Será perguntado o nome do package do seu projeto, utilize o mesmo informado no arquivo: \src\android\app\src\main\AndroidManifest.xml, é algo como: com.nomeempresa.nomeapp

Inicializar no arquivo main

Abra o arquivo lib/main.dart e adicione, os imports:

import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';

E adicione o código abaixo no bloco Main:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(MyApp());
}

firebase_messaging - Receber notificações

Para receber notificações utilizando o Firebase no Flutter, primeiro siga as instruções do tópico anterior, para configurar o Firebase no seu projeto Flutter.

Instalar os pacotes:

flutter pub add firebase_messaging
flutter pub add flutter_local_notifications

Documentação oficial:

Tem um exemplo de implementação aqui:

E outro exemplo aqui:

Para o IOS, adicionar no arquivo: AppDelegate.swift o seguinte:

if #available(iOS 10.0, *) {
	UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}

fica assim:

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    if #available(iOS 10.0, *) {
      UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
    }
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

No arquivo /src/main/AndroidManifest.xml, adicionar:

<meta-data
  android:name="com.google.firebase.messaging.default_notification_channel_id"
  android:value="high_importance_channel" />

A implementação no HomeWidget fica assim:

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';

Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  print('Handling a background message: ${message.messageId}');
}

class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final RefreshController _refreshController = RefreshController(initialRefresh: false);
  final CustomLogger _customLogger = Get.find<CustomLogger>();

  @override
  void initState() {
    super.initState();

    // Run code required to handle interacted messages in an async function
    // as initState() must not be async
    setupInteractedMessage();
  }

  // It is assumed that all messages contain a data field with the key 'type'
  Future<void> setupInteractedMessage() async {
    var _messagingInstance = FirebaseMessaging.instance;

    FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

    NotificationSettings settings = await _messagingInstance.requestPermission(
      alert: true,
      badge: true,
      provisional: false,
      sound: true,
    );

    if (settings.authorizationStatus == AuthorizationStatus.authorized) {
      _customLogger.logInformation('User granted permission to notification');

      //Message when app is in foreground
      FirebaseMessaging.onMessage.listen(_handleMessage);

      // Get any messages which caused the application to open from
      // a terminated state.
      RemoteMessage? initialMessage = await _messagingInstance.getInitialMessage();

      // If the message also contains a data property with a "type" of "chat",
      // navigate to a chat screen
      if (initialMessage != null) {
        _handleMessage(initialMessage);
      }

      // Also handle any interaction when the app is in the background via a
      // Stream listener
      FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage);
    } else {
      _customLogger.logInformation('User declined or has not accepted permission to notification');
    }
  }

  void _handleMessage(RemoteMessage message) {
    //RemoteNotification? notification = message.notification;
    //AndroidNotification? android = message.notification?.android;

    print('messageId: ${message.messageId}, messageType: ${message.messageType}');

    showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: Text(message.notification!.title ?? 'Notificação'),
            content: Text(message.notification!.body!),
            actions: [
              TextButton(
                child: const Text("Ok"),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              )
            ],
          );
        });
  }

	@override
	Widget build(BuildContext context) {
		return Scaffold(
			appBar: AppBar(
				title: Text('Notificação'),
				brightness: Brightness.dark,
			),
			body: Text('Teste'))
	}
}

IOS

No IOS, ao publicar o app para a Apple Store, pode ser que você receba por e-mail o erro: “ITMS-90078: Missing Push Notification Entitlement”. Para contornar esse problema, abra o XCode e siga as instruções descritas aqui: https://stackoverflow.com/a/67074537/618464

firebase_messaging - Analytics com Firebase

Primeiro siga as instruções do tópico acima de configuração do Firebase no flutter, depois instale o pacote:

$ flutter pub add firebase_analytics

Documentação do pacote: https://firebase.flutter.dev/docs/analytics/overview

Firebase Crashlytics

Primeiro siga as instruções do tópico acima de configuração do Firebase no flutter, depois instale o pacote:

$ flutter pub add firebase_crashlytics

Documentação do pacote: https://firebase.flutter.dev/docs/crashlytics/overview/

Leitura de QR Code (qr_code_scanner)

Uma opção para leitura de QR Code é o package QR Code Scanner

Documentação oficial: https://pub.dev/packages/qr_code_scanner

Instalar o plugin:

$ flutter pub add qr_code_scanner

Para utilização no IOS, adicione as linhas abaixo no arquivo Info.plist:

<key>io.flutter.embedded_views_preview</key>
<true/>
<key>NSCameraUsageDescription</key>
<string>This app needs camera access to scan QR codes</string>

No arquivo app/src/main/AndroidManifest.xml adicione:

<uses-permission android:name="android.permission.CAMERA" />

Exemplo de implementação:

https://pub.dev/packages/permission_handler/example

Para utilizar a câmera é necessário verificar a permissão, utilize o package permission_handler e faça o seguinte:

Future<PermissionStatus> _getCameraPermission() async {
	var permissionStatus = await Permission.camera.status;

	if (!permissionStatus.isGranted) {
		permissionStatus = await Permission.camera.request();
	}

	return permissionStatus;
}

Somente quando tiver a permissão exiba o controle.

Se tentar utilizar a câmera sem permissão ocorrerá a exception:

[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: PlatformException(error, java.lang.IllegalStateException: Trying to create a platform view of unregistered type: net.touchcapture.qr.flutterqr/qrview

Pare toda a aplicação e inicie ela novamente. Se ocorrer erro da versão do Kotlin, atualize o arquivo: android\build.gradle, a variável:

ext.kotlin_version = '1.6.10'

eventify (event emitter)

Referências:

Para instalar o pacote execute:

$ flutter pub add eventify

Utilização:

EventEmitter emitter = new EventEmitter(); emitter.on(“test”, null, (ev, context) { print(“${ev.eventName} - ${ev.eventData}”); });

emitter.emit(“test”, null, “Test data”);

RefreshIndicator (pull_to_refresh)

reference: https://api.flutter.dev/flutter/material/RefreshIndicator-class.html

Future _onRefresh() async {
	//TODO: Executar atualizaçlão dos dados
}

Scaffold(
  body: RefreshIndicator(
    onRefresh: _onRefresh,
    child: SingleChildScrollView(
      physics: const AlwaysScrollableScrollPhysics(),
      child: Container(
        margin: const EdgeInsets.all(20.0),
        child: //.. body content
      ),
    ),
  ),
);

NOTA: Se o conteúdo da tela não tiver um scroll maior que o tamanho da tela é é preciso utilizar: physics: const AlwaysScrollableScrollPhysics() para forçar que sempre ocorra a possibilidade do scroll


9- Material Design

Utilizar uma cor customizada como Material Color

https://medium.com/@filipvk/creating-a-custom-color-swatch-in-flutter-554bcdcb27f3

@override Widget build(BuildContext context) { return MaterialApp( title: ‘Flutter Demo’, theme: ThemeData( primarySwatch: createMaterialColor(const Color(0xFF757575)), ), home: const MyHomePage(title: ‘Flutter Demo Home Page’), ); }

MaterialColor createMaterialColor(Color color) { List strengths = [.05]; final swatch = <int, Color>{}; final int r = color.red, g = color.green, b = color.blue;

for (int i = 1; i < 10; i++) {
  strengths.add(0.1 * i);
}
strengths.forEach((strength) {
  final double ds = 0.5 - strength;
  swatch[(strength * 1000).round()] = Color.fromRGBO(
    r + ((ds < 0 ? r : (255 - r)) * ds).round(),
    g + ((ds < 0 ? g : (255 - g)) * ds).round(),
    b + ((ds < 0 ? b : (255 - b)) * ds).round(),
    1,
  );
});
return MaterialColor(color.value, swatch);   }

10- Padrões de arquitetura

MVC x MVP x MVVM

Recomendo o seguinte vídeo que explica muito bem esses conceitos: https://www.youtube.com/watch?v=4KBqWANDbE4&t=1780s


11- Widgets

Abaixo alguns exemplos de Widgets e propriedades que eles aceitam

Text

Text('Seu texto aqui')

Text('Seu texto aqui', style: Theme.of(context).textTheme.headline6)

Text('Seu texto aqui', style: const TextStyle(fontWeight: FontWeight.bold))

Text('Seu texto aqui', style: TextStyle(fontSize: Theme.of(context).textTheme.bodyText2!.fontSize, color: Colors.grey.shade600))

Column

Column(
  children: [
    Text('Text 1'),
    Text('Text 2'),
    Text('Text 3'),
  ],
)

Column(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Text('Text 1'),
    Text('Text 2'),
    Text('Text 3'),
  ],
)

Row

Row(
		children: [
			Text('Text 1'),
	    Text('Text 2'),
	    Text('Text 3'),
		],
)

Scroll horizontal

SingleChildScrollView(
  scrollDirection: Axis.horizontal,
  child: Row(
   children: <Widget>[
     Text('hi'),
     Text('hi'),
     Text('hi'),
   ]
  )
)

Container

Container(
  width: double.infinity,
  height: 100,
  constraints: const BoxConstraints(maxHeight: 200),
  padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 10),
  child: [Widget]
)

//Container com borda arredondada:

Container(
    margin: const EdgeInsets.only(left: 10),
    padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 5),
    decoration: BoxDecoration(
      color: Colors.red.shade300,
      borderRadius: const BorderRadius.all(
        Radius.circular(8.0),
      ),
    ),
    child: const Text('Seu texto aqui', style: TextStyle(color: Colors.white)),
)

ListView

ListView(
  children: <Widget>[
      ListTile(
        title: Text('Valor', style: Theme.of(context).textTheme.headline6),
        subtitle: const Text('Título'),
      )
  ]
)

ListView.builder(
  shrinkWrap: true,
  physics: const ScrollPhysics(),
  itemCount: myItems.length,
  itemBuilder: (context, i) {
    return ListTile(
      title: Text(
        myItems[i].title,
        style: Theme.of(context).textTheme.bodyText1,
      ),
      subtitle: Text(
        myItems[i].text,
        style: Theme.of(context).textTheme.bodyText2,
      ),
      onTap: () { /* Execute action */ },
    );
  }
)

ListView.separated(
  shrinkWrap: true,
  physics: const ScrollPhysics(),
  itemCount: myItems.length,
  itemBuilder: (context, i) {
    return ListTile(
      title: Text(
        myItems[i].title,
        style: Theme.of(context).textTheme.bodyText1,
      ),
      subtitle: Text(
        myItems[i].text,
        style: Theme.of(context).textTheme.bodyText2,
      ),
      onTap: () { /* Execute action */ },
    );
  },
  separatorBuilder: (_, index) => const SizedBox(height: 5, child: Divider())),
)

Botões

Diferentes botões do Material design: https://docs.flutter.dev/development/ui/widgets/material#Buttons

ElevatedButton

ElevatedButton - botão com elevação:

ElevatedButton(
  child: const Text('SIGN IN'),
  onPressed: () {
    controller.signInClick();
  }),

TextButton

TextButton - texto simples clicável:

TextButton(
  child: const Text('CRIAR CONTA'),
  onPressed: () { })

Outlined

Outlined Button - TextButton com borda:

OutlinedButton(
    child: const Text('Click Me'),
    onPressed: () {
      debugPrint('Received click');
    },
)

adicionando ícone:

OutlinedButton(
		child: const Icon(Icons.arrow_right_sharp),
		onPressed: () { }
)

Imagens e ícones

Icon

Icon(Icons.person, size: 30.0, color: Colors.grey.shade400),

Tem a lista de ícones na página: https://api.flutter.dev/flutter/material/Icons-class.html

Asset.Image

Para exibir uma imagem adicionada no projeto:

1- Incluir a imagem na pasta assets 2- Se você criou uma subpasta, por exemplo “assets\icons” ou “assets\images” adicionar essa nova pasta no arquivo pubspec.yam, ou então especificar o nome dos arquivos:

flutter:
  uses-material-design: true
  assets:
    - assets/images/
    - assets/icons/

3- Utilizar na aplicação:

Image.asset('assets/icons/excel-icon-32x32.png')

Exibir uma imagem pela url

(ver package: cached_network_image abaixo)

Seleção / Filtros

Chip (lista de tags)

SizedBox(
  width: double.infinity,
  child: Wrap(
    spacing: 6.0,
    children: taskDetail.taskData.tags
        .map((e) => Chip(
                label: Text(
              e.tagTitle,
            )))
        .toList(),
  ),
)

Dialog

Exibição de Dialog (um modal).

Opções:

Exemplo:

showMyDialog(BuildContext context) {
	var dialog = AlertDialog(
		title: const Text('Título'),
		content: const Text('Minha mensagem'),
		actions: [
			TextButton(
				child: const Text('Cancelar'),
				onPressed: () {},
			),
			TextButton(
				child: const Text('Confirmar'),
				onPressed: () {},
			),
		],
	);

	showDialog(
		context: context,
		builder: (BuildContext context) {
			return dialog;
		},
	);
}

Comentários