MDC-103 Flutter: temas do Material Design com cores, formas, elevação e tipo (Flutter)

logo_components_color_2x_web_96dp.png

Os componentes do Material Design (MDC, na sigla em inglês) ajudam os desenvolvedores a implementar o Material Design. Criados por uma equipe de engenheiros e designers de UX do Google, os MDC apresentam dezenas de componentes de IU bonitos e funcionais e estão disponíveis para Android, iOS, Web e Flutter.material.io/develop

Agora, você pode usar os MDC para personalizar o estilo único dos seus apps mais do que nunca. A recente expansão do Material Design oferece aos designers e desenvolvedores uma maior flexibilidade para expressar a marca do produto.

Nos codelabs MDC-101 e MDC-102, você usou componentes do Material Design (MDC) para criar os elementos básicos do Shrine, um app de comércio eletrônico que vende roupas e artigos domésticos. Esse app contém um fluxo de usuários que começa com uma tela de login e direciona o usuário para uma tela inicial que exibe produtos.

O que você criará

Neste codelab, você personalizará o app Shrine usando:

  • Cor
  • Tipografia
  • Elevação
  • Forma
  • Layout

7f521db8a762f5ee.png 7ac46e5cb6b1e064.png

Componentes e subsistemas do MDC-Flutter neste codelab

  • Temas
  • Tipografia
  • Elevação
  • Lista de imagens

Como você classificaria seu nível de experiência em desenvolvimento com o Flutter?

Iniciante Intermediário Proficiente

Antes de começar

Para começar a desenvolver apps para dispositivos móveis usando o Flutter, é necessário:

  1. fazer o download do SDK do Flutter e instalá-lo;
  2. atualizar seu PATH com o SDK do Flutter SDK;
  3. instalar o Android Studio com os plug-ins do Flutter e do Dart ou o editor que você preferir;
  4. instalar um emulador do Android, um simulador de iOS (exige um Mac com Xcode) ou usar um dispositivo físico.

Para ver mais informações sobre a instalação do Flutter, consulte Primeiros passos: instalação (link em inglês). Para configurar um editor, consulte Primeiros passos: configurar um editor (link em inglês). Você pode usar as opções padrão para instalar um emulador Android, como um smartphone Pixel 3 com a imagem do sistema mais recente. Recomendamos ativar a aceleração de VM, embora não seja obrigatório. Depois que concluir as quatro etapas acima, você poderá retornar ao codelab. Para concluir este codelab, você só precisará instalar o Flutter em uma plataforma (Android ou iOS).

Conferir se o SDK do Flutter está no estado correto

Antes de continuar este codelab, verifique se o SDK está no estado correto. Se o SDK do Flutter tiver sido instalado anteriormente, use o comando flutter upgrade para garantir que o SDK esteja no estado mais recente.

 flutter upgrade

O comando flutter upgrade executará automaticamente o flutter doctor. Se esta for uma nova instalação do Flutter e nenhuma atualização for necessária, execute o flutter doctor manualmente. Você receberá uma notificação se for necessário instalar alguma dependência para concluir a configuração. Ignore as marcas de seleção que não forem relevantes para você (por exemplo, Xcode, se você não quiser desenvolver para iOS).

 flutter doctor

Perguntas frequentes

Está continuando do MDC-102?

Se você concluiu o MDC-102, o código para este codelab já está pronto. Pule para a etapa: Mudar as cores.

Está começando do zero?

Faça o download do app inicial do codelab

Fazer o download do app inicial

O app inicial está localizado no diretório material-components-flutter-codelabs-103-starter_and_102-complete/mdc_100_series.

... ou clone-o do GitHub

Para clonar este codelab do GitHub, execute estes comandos:

git clone https://github.com/material-components/material-components-flutter-codelabs.git
cd material-components-flutter-codelabs/mdc_100_series
git checkout 103-starter_and_102-complete

Configurar seu projeto

As instruções a seguir presumem que você esteja usando o Android Studio (IntelliJ).

Abrir o projeto

1. Abra o Android Studio.

2. Se a tela de boas-vindas for exibida, clique em Open an existing Android Studio project.

3. Navegue até o diretório material-components-flutter-codelabs/mdc_100_series e clique em Open. O projeto será aberto. Você pode ignorar qualquer erro exibido no Dart Analysis antes de criar o projeto pela primeira vez.

4. Se solicitado, faça o seguinte:

  • Instale todas as atualizações de plataforma e de plug-ins ou o FlutterRunConfigurationType.
  • Se o SDK do Dart ou do Flutter não estiver configurado, defina o caminho do SDK do Flutter para o plug-in do Flutter (link em inglês).
  • Configure os frameworks do Android.
  • Clique em "Get dependencies" ou "Run 'flutter packages get'".

Em seguida, reinicie o Android Studio.

Executar o app inicial

As instruções a seguir presumem que você esteja testando em um emulador ou dispositivo Android. Também será possível testar em um simulador ou dispositivo iOS se você tiver o Xcode instalado.

1. Selecione o dispositivo ou emulador. Se o Android Emulator ainda não estiver em execução, selecione Tools -> Android -> AVD Manager para criar um dispositivo virtual e iniciar o emulador. Se já houver um AVD, você poderá iniciar o emulador diretamente do seletor de dispositivos no Android Studio, como mostrado na próxima etapa. Para o simulador do iOS, se ele ainda não estiver em execução, inicie-o na máquina de desenvolvimento selecionando Flutter Device Selection -> Open iOS Simulator.

2. Inicie o app do Flutter:

  • Localize o menu suspenso "Flutter Device Selection" na parte superior da tela do editor e selecione o dispositivo, por exemplo, iPhone SE ou o SDK do Android criado para <version>.
  • Pressione o ícone Play ().

Pronto! Você verá a página de login do app Shrine dos codelabs anteriores no simulador ou emulador.

Android

iOS

Clique em "Next" para ver a página inicial do codelab anterior.

Android

iOS

Um esquema de cores que representa a marca do Shrine foi criado, e o designer quer que você implemente esse esquema no app.

Para começar, vamos importar essas cores para o nosso projeto.

Criar colors.dart

Crie um novo arquivo dart em lib com o nome colors.dart. Importe os componentes do Material Design e adicione constantes de valores de cor:

import 'package:flutter/material.dart';

const kShrinePink50 = Color(0xFFFEEAE6);
const kShrinePink100 = Color(0xFFFEDBD0);
const kShrinePink300 = Color(0xFFFBB8AC);
const kShrinePink400 = Color(0xFFEAA4A4);

const kShrineBrown900 = Color(0xFF442B2D);

const kShrineErrorRed = Color(0xFFC5032B);

const kShrineSurfaceWhite = Color(0xFFFFFBFA);
const kShrineBackgroundWhite = Colors.white;

Paleta de cores personalizada

Este tema de cor foi criado por um designer usando cores personalizadas, mostradas na imagem abaixo. Ele contém cores que foram selecionadas da marca do Shrine e aplicadas ao Material Theme Editor, que as usou como base para criar uma paleta mais completa. Essas cores não são das Paleta de cores do Material Design de 2014 (link em inglês).

O Material Theme Editor organizou as cores em tonalidades marcadas numericamente, incluindo as etiquetas 50, 100, 200 e assim por diante até chegar em 900 para cada cor. O Shrine usa apenas as tonalidades 50, 100 e 300 da amostra rosa e a 900 da amostra marrom.

wlq5aH94SfU47pcalUqOSK57OCX4HnJJTpMVzVrBZreUOE-CrkX2akKrnTbgwf6BQNMBi-nn16jpgQHDeQZixTCeh1A0qTXcxDMTcc2-e6uJg0LPjkXWEVlV7cwS0U1naqpnHToEIQ 1HLdzGp-TIhg2ULijquMw_KQdk18b080CVQN_oECAhiCnFI11Nm3nbcsCIXvZBXULMajAW9NEmGZ7iR_j-eEF6NiODuaike96xVpLwUIzfV4dzTg9uQHsmNG-BDTOd04e6_eRLs--Q

Cada parâmetro colorido de um widget é mapeado para uma cor desses esquemas. Por exemplo, a cor das decorações de um campo de texto que está recebendo ativamente a entrada do usuário precisa ser a cor principal do tema. Se essa cor não for acessível (fácil de ver em relação ao segundo plano), use a classe PrimaryVariant.

Essas variações foram criadas para as diretrizes do Material Design de 2014 e ainda estão disponíveis nas diretrizes atuais (Artigo do sistema de cores, em inglês) e no MDC-Flutter. Para acessá-las no código, basta chamar a cor de base e depois a tonalidade (geralmente, um valor na casa das centenas). Por exemplo, a cor Pink 400 é acessada com o comando: Colors.pink[400].

Não há problema em usar essas paletas para seus designs e códigos. Caso já tenha cores específicas para sua marca, você poderá gerar paletas harmoniosas usando a ferramenta de geração de paleta ou o Material Theme Editor.

Agora que já temos as cores que queremos usar, podemos aplicá-las à IU. Faremos isso definindo os valores de um widget ThemeData que será aplicado à instância de MaterialApp na parte superior da nossa hierarquia de widgets.

Personalizar ThemeData.light()

O Flutter inclui alguns temas integrados. O tema claro é um deles. Em vez de criar um widget ThemeData do zero, copiaremos o tema claro e mudaremos os valores para personalizá-lo em nosso app.

Vamos importar colors.dart em app.dart.

import 'colors.dart';

Em seguida, adicione o código a seguir ao app.dart fora do escopo da classe ShrineApp:

// TODO: Build a Shrine Theme (103)
final ThemeData _kShrineTheme = _buildShrineTheme();

ThemeData _buildShrineTheme() {
  final ThemeData base = ThemeData.light();
  return base.copyWith(
    accentColor: kShrineBrown900,
    primaryColor: kShrinePink100,
    buttonTheme: base.buttonTheme.copyWith(
      buttonColor: kShrinePink100,
      colorScheme: base.colorScheme.copyWith(
        secondary: kShrineBrown900,
      ),
    ),
    buttonBarTheme: base.buttonBarTheme.copyWith(
      buttonTextTheme: ButtonTextTheme.accent,
    ),
    scaffoldBackgroundColor: kShrineBackgroundWhite,
    cardColor: kShrineBackgroundWhite,
    textSelectionColor: kShrinePink100,
    errorColor: kShrineErrorRed,
    // TODO: Add the text themes (103)
    // TODO: Add the icon themes (103)
    // TODO: Decorate the inputs (103)
  );
}

Agora, defina o theme: no final da função build() do ShrineApp (no widget MaterialApp) para ser nosso novo tema:

  // TODO: Add a theme (103)
  theme: _kShrineTheme, // New code

Clique no botão Play. Sua tela de login ficará assim:

Android

iOS

E sua tela inicial será assim:

Android

iOS

Além das mudanças das cores, o designer também forneceu uma tipografia específica para ser usada. O ThemeData do Flutter inclui três temas de texto. Cada um deles é uma coleção de estilos de texto, como "manchete" e "título". Usaremos alguns estilos em nosso app e mudaremos alguns dos valores.

Personalizar o tema do texto

Para importar fontes para o projeto, elas precisam ser adicionadas ao arquivo pubspec.yaml.

No arquivo pubspec.yaml, adicione o código a seguir imediatamente após a tag flutter::

  # TODO: Insert Fonts (103)
  fonts:
    - family: Rubik
      fonts:
        - asset: fonts/Rubik-Regular.ttf
        - asset: fonts/Rubik-Medium.ttf
          weight: 500

Agora você pode acessar e usar a fonte Rubik.

Como solucionar problemas no arquivo pubspec

Poderá haver erros na execução de pub get se você recortar e colar a declaração acima. Se houver erros, comece removendo o espaço em branco no começo da declaração e substitua-o por espaços usando o recuo de dois espaços. Use dois espaços antes de:

fonts:

Quatro espaços antes de:

family: Rubik

E assim por diante.

Se a mensagem Mapping values are not allowed here for exibida, verifique o recuo da linha que causou o problema e o recuo das linhas acima dela.

Em login.dart, mude o código a seguir em Column():

Column(
  children: <Widget>[
    Image.asset('assets/diamond.png'),
    SizedBox(height: 16.0),
    Text(
      'SHRINE',
      style: Theme.of(context).textTheme.headline5,
    ),
  ],
)

Em app.dart, adicione o código a seguir após _buildShrineTheme():

// TODO: Build a Shrine Text Theme (103)
TextTheme _buildShrineTextTheme(TextTheme base) {
  return base.copyWith(
    headline5: base.headline5.copyWith(
      fontWeight: FontWeight.w500,
    ),
    headline6: base.headline6.copyWith(
        fontSize: 18.0
    ),
    caption: base.caption.copyWith(
      fontWeight: FontWeight.w400,
      fontSize: 14.0,
    ),
    bodyText1: base.bodyText1.copyWith(
      fontWeight: FontWeight.w500,
      fontSize: 16.0,
    ),
  ).apply(
    fontFamily: 'Rubik',
    displayColor: kShrineBrown900,
    bodyColor: kShrineBrown900,
  );
}

Esse código usa um TextTheme e muda a forma como as manchetes, os títulos e as legendas são exibidos.

Usar a fontFamily dessa maneira faz que as mudanças sejam aplicadas somente aos valores de escala de tipografia especificados em copyWith() (manchete, título, legenda).

Para algumas fontes, definimos um fontWeight personalizado. O widget FontWeight tem valores convenientes para as casas das centenas. Para fontes, w500 (o peso 500) costuma ser o valor médio, e w400 geralmente é o valor normal.

Usar os novos temas de textos

Adicione os estes temas ao _buildShrineTheme após errorColor:

// TODO: Add the text themes (103)

textTheme: _buildShrineTextTheme(base.textTheme),
primaryTextTheme: _buildShrineTextTheme(base.primaryTextTheme),
accentTextTheme: _buildShrineTextTheme(base.accentTextTheme),

Clique no botão Stop e, em seguida, no botão Play.

O texto na tela inicial e de login parece diferente. Alguns textos usam a fonte Rubik, e outros são renderizados em marrom, em vez de preto ou branco.

Android

iOS

Os ícones ainda são brancos. Isso ocorre porque existe um tema separado para ícones.

Usar um tema de ícone principal personalizado

Adicione-o à função _buildShrineTheme():

    // TODO: Add the icon theme (103)
    primaryIconTheme: base.iconTheme.copyWith(
      color: kShrineBrown900
    ),

Clique no botão Play.

Android

iOS

Os ícones na barra de apps são marrons agora.

Reduzir o texto

As etiquetas estão muito grandes.

Em home.dart, mude children: da coluna mais interna:

// TODO: Change innermost Column (103)
children: <Widget>[
// TODO: Handle overflowing labels (103)

  Text(
    product == null ? '' : product.name,
    style: theme.textTheme.button,
    softWrap: false,
    overflow: TextOverflow.ellipsis,
    maxLines: 1,
  ),
  SizedBox(height: 4.0),
  Text(
    product == null ? '' : formatter.format(product.price),
    style: theme.textTheme.caption,
  ),
  // End new code
],

Centralizar e abaixar o texto

Queremos centralizar as etiquetas e alinhar o texto com a parte inferior de cada card, em vez da parte inferior de cada imagem.

Mova as etiquetas para o final (abaixo) do eixo principal e centralize-as:

// TODO: Align labels to the bottom and center (103)

  mainAxisAlignment: MainAxisAlignment.end,
  crossAxisAlignment: CrossAxisAlignment.center,

Salve o projeto.

Android

iOS

Estamos quase lá, mas o texto ainda não está centralizado no card.

Mude o alinhamento entre eixos da coluna mãe:

// TODO: Center items on the card (103)

    crossAxisAlignment: CrossAxisAlignment.center,

Salve o projeto. Sua tela inicial ficará assim:

Android

iOS

Parece muito melhor.

Atribuir um tema aos campos de texto

Também é possível aplicar um tema à decoração dos campos de texto usando um InputDecorationTheme.

Em app.dart, no método _buildShrineTheme(), especifique um valor de inputDecorationTheme::

// TODO: Decorate the inputs (103)
inputDecorationTheme: InputDecorationTheme(
  border: OutlineInputBorder(),
),

No momento, os campos de texto têm uma decoração filled. Vamos remover isso. Se você remover filled e especificar inputDecorationTheme, os campos de texto usarão o estilo delineado.

Em login.dart, remova os valores filled: true:

// Remove filled: true values (103)
TextField(
  controller: _usernameController,
  decoration: InputDecoration(
    // Removed filled: true
    labelText: 'Username',
  ),
),
SizedBox(height: 12.0),
TextField(
  controller: _passwordController,
  decoration: InputDecoration(
    // Removed filled: true
    labelText: 'Password',
  ),
  obscureText: true,
),

Clique no botão "Flutter Hot Restart" no menu "Run" para reiniciar o app desde o início. A tela de login ficará como no exemplo a seguir quando o campo "Username" estiver ativo (quando o usuário estiver digitando nele):

Android

iOS

Comece a digitar em um campo de texto. As decorações e os marcadores flutuantes serão renderizados usando a cor primária. Mas eles não são fáceis de ver. O app não é acessível para pessoas com problemas para distinguir pixels sem um contraste de cor alto o suficiente. Para ver mais informações sobre cores acessíveis, consulte a seção "Accessible colors" no artigo sobre as cores (link em inglês) do Material Design. Vamos especificar uma focusedBorder: no inputDecorationTheme: para substituir a cor de destaque do campo de texto para ser a PrimaryVariant que o designer nos forneceu no tema de cores acima.

Em app.dart, especifique uma focusedBorder: no inputDecorationTheme: :

// TODO: Decorate the inputs (103)
inputDecorationTheme: InputDecorationTheme(
  focusedBorder: OutlineInputBorder(
    borderSide: BorderSide(
      width: 2.0,
      color: kShrineBrown900,
    ),
  ),
  border: OutlineInputBorder(),
),

Em seguida, mudaremos a propriedade labelStyle de ambos os campos de texto para colorir a etiqueta no tema de cores fornecido pelo designer.

Em login.dart, adicione um labelStyle: em ambos os widgets TextField de InputDecoration():

TextField(
  controller: _usernameController,
  decoration: InputDecoration(
    labelText: 'Username',
    labelStyle: TextStyle(color: Theme.of(context).accentColor),
  ),
),
SizedBox(height: 12.0),
TextField(
  controller: _passwordController,
  decoration: InputDecoration(
    labelText: 'Password',
    labelStyle: TextStyle(color: Theme.of(context).accentColor),
  ),
),

Para usar estilos de etiqueta diferentes para quando o campo de texto estiver em foco ou não, configure um FocusNode para cada widget TextField e uma condicional para tornar o labelStyle dinâmico dependendo se o widget está em foco ou não.

Em login.dart, vamos inicializar os FocusNodes e a cor da etiqueta sem foco na parte superior da classe _LoginPageState dos nossos controladores de campo de texto:

class _LoginPageState extends State<LoginPage> {
  final _usernameController = TextEditingController();
  final _passwordController = TextEditingController();
  final _unfocusedColor = Colors.grey[600];
  final _usernameFocusNode = FocusNode();
  final _passwordFocusNode = FocusNode();

Substitua o initState e adicione um listener aos FocusNodes:

@override
void initState() {
  super.initState();
  _usernameFocusNode.addListener(() {
      setState(() {
        //Redraw so that the username label reflects the focus state
      });
   });
  _passwordFocusNode.addListener(() {
      setState(() {
        //Redraw so that the password label reflects the focus state
      });
   });
}

Por fim, adicione a propriedade focusNode: nos widgets TextField e adicione uma condicional para o labelStyle: em InputDecoration():

TextField(
  controller: _usernameController,
  decoration: InputDecoration(
    labelText: 'Username',
    labelStyle: TextStyle(
        color: _usernameFocusNode.hasFocus
           ? Theme.of(context).accentColor
           : _unfocusedColor),
  ),
  focusNode: _usernameFocusNode,
),
SizedBox(height: 12.0),
TextField(
  controller: _passwordController,
  decoration: InputDecoration(
    labelText: 'Password',
    labelStyle: TextStyle(
        color: _passwordFocusNode.hasFocus
           ? Theme.of(context).accentColor
           : _unfocusedColor),
  ),
  focusNode: _passwordFocusNode,
),

Clique no botão Play.

Android

iOS

Agora que você definiu o estilo da página com cores e tipografia específicas para combinar com o Shrine, vamos dar uma olhada nos cards que mostram os produtos no app. No momento, os cards aparecem em uma superfície branca ao lado da navegação do site.

Ajustar elevação do card

Em home.dart, adicione um valor de elevation: aos cards:

// TODO: Adjust card heights (103)

    elevation: 0.0,

Salve o projeto.

Android

iOS

Você removeu a sombra embaixo dos cards.

Mude a elevação dos componentes na tela de login para complementar esse estilo.

Mudar a elevação do botão NEXT

A elevação padrão para a classe RaisedButtons é 2. Vamos aumentá-la.

Em login.dart, adicione um valor de elevation: ao RaisedButton NEXT:

RaisedButton(
  child: Text('NEXT'),
  elevation: 8.0, // New code

Clique no botão "Flutter Hot Restart" no menu "Run" para reiniciar o app desde o início. Sua tela de login ficará assim:

Android

iOS

O Shrine tem um estilo geométrico que define elementos usando formas octogonais ou retangulares. Vamos implementar esse estilo de forma nos cards na tela inicial e nos campos de texto e botões da tela de login.

Mudar as formas dos campos de texto na tela de login

Em app.dart, importe um arquivo especial de borda com cantos recortados:

import 'supplemental/cut_corners_border.dart';

Ainda em app.dart, adicione uma forma com cantos recortados no tema de decoração do campo de texto:

// TODO: Decorate the inputs (103)
inputDecorationTheme: InputDecorationTheme(
  focusedBorder: CutCornersBorder(
    borderSide: BorderSide(
      width: 2.0,
      color: kShrineBrown900,
    ),
  ),
  border: CutCornersBorder(), // Replace code
),

Mudar as formas dos botões na tela de login

Em login.dart, adicione uma borda retangular chanfrada ao botão CANCEL:

FlatButton(
  child: Text('CANCEL'),
  shape: BeveledRectangleBorder(
    borderRadius: BorderRadius.all(Radius.circular(7.0)),
  ),

O FlatButton não tem uma forma visível. Então, por que estamos adicionando um ícone de borda a ele? Fazemos isso para que a animação de ondulação seja ligada à mesma forma quando for tocada.

Agora, adicione a mesma forma ao botão NEXT:

RaisedButton(
  child: Text('NEXT'),
  elevation: 8.0,
  shape: BeveledRectangleBorder(
    borderRadius: BorderRadius.all(Radius.circular(7.0)),
  ),

Para mudar a forma de todos os botões, também podemos atualizar o buttonTheme em app.dart. Você poderá fazer depois, como um desafio.

Clique no botão "Flutter Hot Restart" no menu "Run" para reiniciar o app desde o início:

Android

iOS

Agora, vamos modificar o layout para mostrar os cards em proporções e tamanhos distintos, de modo que cada card seja diferente dos demais.

Substituir uma GridView por uma AsymmetricView

Já criamos os arquivos para um layout assimétrico.

Em home.dart, altere todo o arquivo para ficar como o código a seguir:

import 'package:flutter/material.dart';

import 'model/products_repository.dart';
import 'model/product.dart';
import 'supplemental/asymmetric_view.dart';

class HomePage extends StatelessWidget {
  // TODO: Add a variable for Category (104)

  @override
  Widget build(BuildContext context) {
  // TODO: Return an AsymmetricView (104)
  // TODO: Pass Category variable to AsymmetricView (104)
    return Scaffold(
      appBar: AppBar(
        brightness: Brightness.light,
        leading: IconButton(
          icon: Icon(Icons.menu),
          onPressed: () {
            print('Menu button');
          },
        ),
        title: Text('SHRINE'),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.search),
            onPressed: () {
              print('Search button');
            },
          ),
          IconButton(
            icon: Icon(Icons.tune),
            onPressed: () {
              print('Filter button');
            },
          ),
        ],
      ),
      body: AsymmetricView(products: ProductsRepository.loadProducts(Category.all)),
    );
  }
}

Salve o projeto.

Android

iOS

Agora, os produtos rolam horizontalmente na tela em um padrão inspirado pela costura. Além disso, o texto da barra de status (mostrando o tempo e a rede na parte superior) agora é exibido em preto. Isso ocorre porque mudamos o brilho de AppBar para ser claro, brightness: Brightness.light.

As cores são uma maneira eficiente de expressar sua marca, e uma pequena mudança de cor pode ter um grande efeito na experiência do usuário. Para testar isso, veremos como o Shrine seria se o esquema de cores da marca fosse completamente diferente.

Modificar cores

Em colors.dart, adicione este código:

const kShrinePurple = Color(0xFF5D1049);
const kShrineBlack = Color(0xFF000000);

Em app.dart, mude as funções _buildShrineTheme() e _buildShrineTextTheme para:

ThemeData _buildShrineTheme() {
  final ThemeData base = ThemeData.light();
  return base.copyWith(
    primaryColor: kShrinePurple,
    buttonTheme: base.buttonTheme.copyWith(
      buttonColor: kShrinePurple,
      textTheme: ButtonTextTheme.primary,
      colorScheme: ColorScheme.light().copyWith(primary: kShrinePurple)
    ),
    scaffoldBackgroundColor: kShrineSurfaceWhite,
    textTheme: _buildShrineTextTheme(base.textTheme),
    primaryTextTheme: _buildShrineTextTheme(base.primaryTextTheme),
    accentTextTheme: _buildShrineTextTheme(base.accentTextTheme),
    primaryIconTheme: base.iconTheme.copyWith(
      color: kShrineSurfaceWhite
    ),
    inputDecorationTheme: InputDecorationTheme(
      focusedBorder: CutCornersBorder(
        borderSide: BorderSide(
          width: 2.0,
          color: kShrinePurple,
        ),
      ),
      border: CutCornersBorder(),
    ),
  );
}

TextTheme _buildShrineTextTheme(TextTheme base) {
  return base.copyWith(
    headline5: base.headline5.copyWith(
      fontWeight: FontWeight.w500,
    ),
    headline6: base.headline6.copyWith(
        fontSize: 18.0,
    ),
    caption: base.caption.copyWith(
      fontWeight: FontWeight.w400,
      fontSize: 14.0,
    ),
    bodyText1: base.bodyText1.copyWith(
      fontWeight: FontWeight.w500,
      fontSize: 16.0,
    ),
  ).apply(
    fontFamily: 'Rubik',
  );
}

Em login.dart, defina a cor preta para o logotipo de losango:

Image.asset(
  'assets/diamond.png',
  color: kShrineBlack, // New code
),

Em home.dart, altere o brilho do widget AppBar para escuro:

brightness: Brightness.dark,

Salve o projeto. O novo tema será exibido.

Android

iOS

Android

iOS

O resultado é muito diferente. Vamos reverter esse código de cores antes de passar para o codelab 104.

Fazer o download do código inicial do MDC-104

Agora, você já criou um app que parece seguir as especificações do seu designer.

Próximas etapas

Até agora, você já usou os seguintes componentes do MDC: tema, tipografia, elevação e forma. Você pode ver mais componentes e subsistemas na biblioteca MDC-Flutter.

Analise os arquivos no diretório supplemental para ver como fizemos a rolagem horizontal e a grade de layout assimétrica.

E se o design do app planejado tiver elementos que não têm componentes na biblioteca MDC? No codelab MDC-104: componentes avançados do Material Design, mostraremos como criar componentes personalizados usando a biblioteca MDC para criar uma aparência específica para o app.

Próximo codelab

Este codelab exigiu esforço e tempo normais para ser concluído

Concordo totalmente Concordo Não concordo nem discordo Discordo Discordo totalmente

Quero continuar usando componentes do Material Design no futuro

Concordo totalmente Concordo Não concordo nem discordo Discordo Discordo totalmente