MDC-103 Flutter: тематика материала с указанием цвета, формы, высоты и типа

1. Введение

logo_components_color_2x_web_96dp.png

Компоненты Material (MDC) помогают разработчикам внедрять Material Design. Созданные командой инженеров и UX-дизайнеров Google, MDC включают в себя десятки красивых и функциональных компонентов пользовательского интерфейса и доступны для Android, iOS, веб-приложений и Flutter.material.io/develop

Теперь вы можете использовать Material Flutter для персонализации уникального стиля ваших приложений как никогда раньше. Недавнее расширение Material Design предоставляет дизайнерам и разработчикам большую гибкость в выражении фирменного стиля своего продукта.

В рамках практических занятий MDC-101 и MDC-102 вы использовали Material Flutter для создания базовой части приложения Shrine , приложения для электронной коммерции, продающего одежду и товары для дома. Это приложение содержит пользовательский интерфейс, который начинается с экрана входа в систему, а затем переводит пользователя на главный экран с отображением товаров.

Что вы построите

В этом практическом занятии вы настроите приложение Shrine, используя следующие инструменты:

  • Цвет
  • Типография
  • Высота
  • Форма
  • Макет

Android

iOS

Страница входа в систему Shrine, оформленная в коричнево-розовых тонах.

Страница входа в систему Shrine, оформленная в коричнево-розовых тонах.

Страница товаров Shrine с верхней панелью приложения и асимметричной, горизонтально прокручиваемой сеткой, заполненной товарами, оформлена в розовых тонах.

Компоненты и подсистемы Material Flutter в этом практическом занятии.

  • Темы
  • Типография
  • Высота
  • Список изображений

Как бы вы оценили свой уровень опыта в разработке на Flutter?

Новичок Средний Профессионал

2. Настройте среду разработки Flutter.

Для выполнения этой лабораторной работы вам понадобятся два программных компонента: Flutter SDK и редактор .

Вы можете выполнить это практическое задание, используя любое из следующих устройств:

  • Физическое устройство Android или iOS , подключенное к компьютеру и настроенное на режим разработчика.
  • Симулятор iOS (требуется установка инструментов Xcode).
  • Эмулятор Android (требуется настройка в Android Studio).
  • Для работы требуется браузер (для отладки необходим Chrome).
  • Если вы разрабатываете настольное приложение для Windows , Linux или macOS , вам необходимо работать на той платформе, на которой вы планируете его развернуть. Таким образом, если вы хотите разработать настольное приложение для Windows, вам необходимо использовать Windows для доступа к соответствующей цепочке сборки. Существуют специфические требования к операционной системе, которые подробно описаны в документации docs.flutter.dev/desktop .

3. Скачайте стартовое приложение Codelab.

Продолжение темы MDC-102?

Если вы прошли курс MDC-102, ваш код должен быть готов для этой практической работы. Перейдите к шагу: Изменение цветов .

Начинать с нуля?

Скачайте стартовое приложение Codelab.

Стартовое приложение находится в каталоге material-components-flutter-codelabs-103-starter_and_102-complete/mdc_100_series .

...или клонируйте его с GitHub

Чтобы клонировать этот код с GitHub, выполните следующие команды:

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

Откройте проект и запустите приложение.

  1. Откройте проект в выбранном вами редакторе.
  2. Следуйте инструкциям, чтобы запустить приложение в разделе « Начало работы: Тестовая версия » для выбранного вами редактора.

Успех! На вашем устройстве должна отобразиться страница входа в Shrine, которую вы видели в предыдущих кодовых заданиях.

Android

iOS

страница входа в святилище без тематической тематики

страница входа в святилище без тематической тематики

Нажмите «Далее», чтобы перейти на страницу товара.

Android

iOS

Нетематическая страница сетки товаров «Святилище»

Нетематическая страница сетки товаров «Святилище»

4. Измените цвета.

Создана цветовая схема, отражающая бренд Shrine, и дизайнер хотел бы, чтобы вы использовали эту цветовую схему во всем приложении Shrine.

Для начала давайте импортируем эти цвета в наш проект.

Создать colors.dart

Создайте новый файл Dart в lib под названием colors.dart . Импортируйте material.dart и добавьте const Color :

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;

Пользовательская цветовая палитра

Эта цветовая схема была создана дизайнером с использованием пользовательских цветов (показано на изображении ниже). Она содержит цвета, выбранные из фирменного стиля Shrine и примененные к редактору тем Material, что позволило расширить их палитру и создать более полную коллекцию. (Эти цвета не входят в палитры Material 2014 года .)

Редактор тем Material Design организовал их по оттенкам, обозначенным числовыми номерами, включая 50, 100, 200, ... до 900 для каждого цвета. Shrine использует только оттенки 50, 100 и 300 из розовой палитры и 900 из коричневой палитры.

d0362cb45c565a8e.jpeg470b0e1c2669ae2.png

Каждый цветной параметр виджета сопоставляется с цветом из этих цветовых схем. Например, цвет оформления текстового поля, когда оно активно принимает ввод, должен соответствовать основному цвету темы. Если этот цвет недоступен (его трудно заметить на фоне), используйте другой цвет.

Теперь, когда у нас есть нужные цвета, мы можем применить их к пользовательскому интерфейсу. Для этого мы установим значения виджета ThemeData , который мы применяем к экземпляру MaterialApp в верхней части иерархии виджетов.

Настройте ThemeData.light()

Flutter включает в себя несколько встроенных тем оформления. Светлая тема — одна из них. Вместо того чтобы создавать виджет ThemeData с нуля, мы скопируем светлую тему и изменим значения, чтобы настроить их под наше приложение.

Давайте импортируем colors.dart в app.dart.

import 'colors.dart';

Затем добавьте следующий код в файл app.dart вне области видимости класса ShrineApp:

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

ThemeData _buildShrineTheme() {
  final ThemeData base = ThemeData.light(useMaterial3: true);
  return base.copyWith(
    colorScheme: base.colorScheme.copyWith(
      primary: kShrinePink100,
      onPrimary: kShrineBrown900,
      secondary: kShrineBrown900,
      error: kShrineErrorRed,
    ),
    // TODO: Add the text themes (103)
    // TODO: Decorate the inputs (103)
  );
}

Теперь зададим theme: в конце функции build() ShrineApp (в виджете MaterialApp) укажите нашу новую тему:

  // TODO: Customize the theme (103)
  theme: _kShrineTheme, // New code

Сохраните свой проект. Теперь ваш экран входа в систему должен выглядеть так:

Android

iOS

Страница входа в систему храма в розово-коричневой тематике

Страница входа в систему храма в розово-коричневой тематике

5. Измените типографику и стили подписей.

Помимо изменения цвета, дизайнер также предоставил нам определённые типографические настройки для использования. Flutter's ThemeData включает 3 текстовые темы. Каждая текстовая тема представляет собой набор стилей текста, таких как «заголовок» и «название». Мы будем использовать несколько стилей для нашего приложения и изменим некоторые значения.

Настройте текстовую тему.

Для импорта шрифтов в проект их необходимо добавить в файл pubspec.yaml.

В файле pubspec.yaml сразу после тега flutter: добавьте следующее:

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

Теперь вы можете получить доступ к шрифту Rubik и использовать его.

Устранение неполадок с файлом pubspec

При копировании и вставке приведенного выше объявления могут возникнуть ошибки при выполнении команды `pub get` . Если возникнут ошибки, начните с удаления начального пробела и замены его пробелами, используя отступ в 2 пробела (два пробела перед...).

fonts:

, четыре места перед

family: Rubik

, и так далее.)

Если вы видите сообщение "Здесь не допускаются значения сопоставления" , проверьте отступ строки, в которой возникла проблема, и отступ строк выше.

В файле login.dart измените следующий код внутри Column() :

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

В app.dart добавьте следующий код после _buildShrineTheme() :

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

Эта функция берет тему оформления TextTheme и изменяет внешний вид заголовков, названий и подписей.

Применение шрифта fontFamily таким образом вносит изменения только в значения типографической шкалы, указанные в copyWith() (заголовок, название, подпись).

Для некоторых шрифтов мы задаем пользовательское значение fontWeight с шагом в 100: w500 (значение 500) соответствует среднему типу, а w400 — обычному.

Используйте новые текстовые темы .

После возникновения ошибки добавьте следующие темы в файл _buildShrineTheme :

// TODO: Add the text themes (103)
textTheme: _buildShrineTextTheme(base.textTheme),
textSelectionTheme: const TextSelectionThemeData(
  selectionColor: kShrinePink100,
),

Сохраните свой проект. На этот раз также перезапустите приложение (так называемый «горячий перезапуск »), поскольку мы изменили шрифты.

Android

iOS

Страница сеткой товаров Shrine с примененными текстовыми темами.

Текст на экране входа и главном экране выглядит по-разному — часть текста использует шрифт Rubik, а другая часть отображается коричневым цветом вместо черного или белого. Иконки также отображаются коричневым цветом.

Свернуть текст

Надписи слишком большие.

В home.dart измените children: самого внутреннего столбца:

// TODO: Change innermost Column (103)
children: <Widget>[
// TODO: Handle overflowing labels (103)
  Text(
    product.name,
    style: theme.textTheme.button,
    softWrap: false,
    overflow: TextOverflow.ellipsis,
    maxLines: 1,
  ),
  const SizedBox(height: 4.0),
  Text(
    formatter.format(product.price),
    style: theme.textTheme.bodySmall,
  ),
  // End new code
],

Выровняйте текст по центру и перетащите его.

Мы хотим центрировать подписи и выровнять текст по нижнему краю каждой карточки, а не по нижнему краю каждого изображения.

Переместите подписи в конец (вниз) основной оси и отцентрируйте их:

  // TODO: Align labels to the bottom and center (103)
  mainAxisAlignment: MainAxisAlignment.end,
  crossAxisAlignment: CrossAxisAlignment.center,

Сохраните свой проект.

Android

iOS

Страница с сеткой товаров Shrine с различным выравниванием текста.

Страница с сеткой товаров Shrine с различным выравниванием текста.

Так выглядит намного лучше.

Настройте оформление текстовых полей

Вы также можете изменить оформление текстовых полей с помощью InputDecorationTheme .

В app.dart , в методе _buildShrineTheme() , укажите значение inputDecorationTheme: value:

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

Сейчас текстовые поля имеют filled оформление. Давайте его удалим. Удаление filled и указание inputDecorationTheme придаст текстовым полям стиль контура.

В login.dart удалите значения filled: true :

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

Горячая перезагрузка. При активном поле «Имя пользователя» (во время ввода текста) экран входа в систему должен выглядеть примерно так:

Android

iOS

Страница входа в Shrine с выделенным полем для имени пользователя.

Страница входа в Shrine с выделенным полем для имени пользователя.

При вводе текста в текстовое поле границы и плавающие подписи отображаются основным цветом. Но это не очень хорошо видно. Это недоступно для людей, которым трудно различать пиксели с недостаточно высоким цветовым контрастом. (Более подробную информацию см. в статье «Цвет и доступность» из руководства Material Design.)

В app.dart укажите focusedBorder: в поле inputDecorationTheme: :

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

Далее укажите floatingLabelStyle: в поле inputDecorationTheme: :

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

Наконец, давайте сделаем так, чтобы кнопка «Отмена» использовала дополнительный цвет вместо основного для повышения контрастности.

TextButton(
  child: const Text('CANCEL'),
  onPressed: () {
    _usernameController.clear();
    _passwordController.clear();
  },
  style: TextButton.styleFrom(
    primary: Theme.of(context).colorScheme.secondary,
  ),
),

Сохраните свой проект.

Android

iOS

Страница входа в систему храма с доступной кнопкой ОТМЕНА

Страница входа в систему храма с доступной кнопкой ОТМЕНА

6. Отрегулируйте высоту.

Теперь, когда вы оформили страницу, используя цвета и типографику, соответствующие стилю Shrine, давайте отрегулируем высоту.

Измените высоту кнопки «Далее».

Значение по умолчанию для ElevatedButton равно 2. Давайте поднимем его выше.

В login.dart добавьте свойство style: value к элементу NEXT ElevatedButton:

ElevatedButton(
  child: const Text('NEXT'),
  onPressed: () {
    Navigator.pop(context);
  },
  style: ElevatedButton.styleFrom(
    foregroundColor: kShrineBrown900,
    backgroundColor: kShrinePink100,
    elevation: 8.0,
  ),
),

Сохраните свой проект.

Android

iOS

Страница входа в систему Shrine с улучшенной кнопкой «ДАЛЕЕ».

Страница входа в систему Shrine с улучшенной кнопкой «ДАЛЕЕ».

Отрегулировать высоту карты

В данный момент карточки лежали на белой поверхности рядом с навигацией по сайту.

В home.dart добавьте значение elevation: к элементам Cards:

// TODO: Adjust card heights (103)
elevation: 0.0,

Сохраните проект.

Android

iOS

Сетка товаров Shrine без указания высоты для каждой карточки.

Сетка товаров Shrine без указания высоты для каждой карточки.

Вы убрали тень под карточками.

7. Добавьте форму

Shrine отличается интересным геометрическим стилем, в котором элементы имеют восьмиугольную или прямоугольную форму. Давайте применим этот стиль к карточкам на главном экране, а также к текстовым полям и кнопкам на экране входа в систему.

Измените форму текстовых полей на экране входа в систему.

В app.dart импортируйте следующий файл:

import 'supplemental/cut_corners_border.dart';

В файле app.dart измените тему оформления текстового поля, чтобы использовать рамку со срезанными углами:

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

Изменить форму кнопок на экране входа в систему

В login.dart добавьте прямоугольную рамку со скошенными краями к кнопке ОТМЕНА :

TextButton(
  child: const Text('CANCEL'),
  onPressed: () {
    _usernameController.clear();
    _passwordController.clear();
  },
  style: TextButton.styleFrom(
    foregroundColor: kShrineBrown900,
    shape: const BeveledRectangleBorder(
      borderRadius: BorderRadius.all(Radius.circular(7.0)),
    ),
  ),
),

У кнопки TextButton нет видимой формы, так зачем добавлять границу? Таким образом, анимация ряби при касании будет привязана к той же форме.

Теперь добавьте ту же фигуру к кнопке "Далее":

ElevatedButton(
  child: const Text('NEXT'),
  onPressed: () {
    Navigator.pop(context);
  },
  style: ElevatedButton.styleFrom(
    foregroundColor: kShrineBrown900,
    backgroundColor: kShrinePink100,
    elevation: 8.0,
    shape: const BeveledRectangleBorder(
      borderRadius: BorderRadius.all(Radius.circular(7.0)),
    ),
  ),
),

Для изменения формы всех кнопок можно также использовать elevatedButtonTheme или textButtonTheme в app.dart . Это остаётся заданием для обучающегося!

Горячая перезагрузка.

Android

iOS

Страница входа в систему Shrine с применением тематического оформления в виде геометрических фигур.

Страница входа в систему Shrine с применением тематического оформления в виде геометрических фигур.

8. Измените макет.

Далее изменим макет, чтобы отображать карточки с разными соотношениями сторон и размерами, так чтобы каждая карточка выглядела уникальной по сравнению с другими.

Замените GridView на AsymmetricView

Мы уже подготовили файлы для асимметричной компоновки.

В home.dart добавьте следующий импорт:

import 'supplemental/asymmetric_view.dart';

Удалите строку _buildGridCards и замените её body :

body: AsymmetricView(
  products: ProductsRepository.loadProducts(Category.all),
),

Сохраните проект.

Android

iOS

Страница товара Shrine с асимметричным горизонтальным прокручиваемым макетом.

Страница товара Shrine с асимметричным горизонтальным прокручиваемым макетом.

Теперь товары расположены горизонтально, образуя узор, вдохновленный плетением.

9. Попробуйте другую тему (необязательно)

Цвет — мощный инструмент для выражения вашего бренда, и даже небольшое изменение цвета может существенно повлиять на пользовательский опыт. Чтобы это проверить, давайте посмотрим, как будет выглядеть Shrine, если цветовая схема бренда будет немного другой.

Изменить цвета

В файл colors.dart добавьте следующий цвет:

const kShrinePurple = Color(0xFF5D1049);

В app.dart измените функцию _buildShrineTheme() следующим образом:

ThemeData _buildShrineTheme() {
  final ThemeData base = ThemeData.light();
  return base.copyWith(
    colorScheme: base.colorScheme.copyWith(
      primary: kShrinePurple,
      secondary: kShrinePurple,
      error: kShrineErrorRed,
    ),
    scaffoldBackgroundColor: kShrineSurfaceWhite,
    textSelectionTheme: const TextSelectionThemeData(
      selectionColor: kShrinePurple,
    ),
    appBarTheme: const AppBarTheme(
      foregroundColor: kShrineBrown900,
      backgroundColor: kShrinePink100,
    ),

    inputDecorationTheme: const InputDecorationTheme(
      border: CutCornersBorder(),
      focusedBorder: CutCornersBorder(
        borderSide: BorderSide(
          width: 2.0,
          color: kShrinePurple,
        ),
      ),
      floatingLabelStyle: TextStyle(
        color: kShrinePurple,
      ),
    ),
  );
}

Перезагрузка системы. Новая тема должна отобразиться.

Android

iOS

Страница входа в систему храма с фиолетово-розовой тематикой.

Страница входа в систему храма с фиолетово-розовой тематикой.

Android

iOS

Страница товара Shrine в розовой гамме

Страница товара Shrine в розовой гамме

Результат совсем другой! Давайте вернем _buildShrineTheme app.dart's к тому состоянию, в котором он был до этого шага. Или скачаем стартовый код из примера 104.

10. Поздравляем!

К этому моменту вы уже создали приложение, которое соответствует техническим требованиям вашего дизайнера.

Следующие шаги

Вы уже использовали следующие компоненты Material Flutter: theme, typography, elevation и shape. Вы можете изучить другие компоненты и подсистемы в библиотеке Material Flutter.

Изучите файлы в supplemental директории, чтобы узнать, как мы создали асимметричную сетку с горизонтальной прокруткой.

Что делать, если в запланированном дизайне приложения есть элементы, для которых нет компонентов в библиотеке? В курсе MDC-104: Расширенные компоненты Material мы покажем, как создавать пользовательские компоненты с помощью библиотеки Material Flutter для достижения желаемого внешнего вида.

Мне удалось выполнить это практическое задание за разумное время и с разумными затратами усилий.

Полностью согласен Соглашаться Нейтральный Не согласен Категорически не согласен

Я хотел бы и в будущем продолжать использовать компоненты Material.

Полностью согласен Соглашаться Нейтральный Не согласен Категорически не согласен