1. Введение
Material Components (MDC) помогают разработчикам реализовать Material Design. Созданный командой инженеров и UX-дизайнеров Google, MDC включает в себя десятки красивых и функциональных компонентов пользовательского интерфейса и доступен для Android, iOS, Интернета и Flutter.material.io/develop. |
Теперь вы можете использовать Material Flutter для более индивидуальной настройки уникального стиля ваших приложений, чем когда-либо. Недавнее расширение Material Design дает дизайнерам и разработчикам большую гибкость в представлении бренда своего продукта.
В кодовых лабораториях MDC-101 и MDC-102 вы использовали Material Flutter для создания основ приложения под названием Shrine , приложения для электронной коммерции, которое продает одежду и товары для дома. Это приложение содержит пользовательский поток, который начинается с экрана входа в систему, а затем переносит пользователя на главный экран, на котором отображаются продукты.
Что ты построишь
В этой кодовой лаборатории вы настроите приложение Shrine, используя:
- Цвет
- Типография
- Высота
- Форма
- Макет
Андроид | iOS |
Компоненты и подсистемы 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
Откройте проект и запустите приложение
- Откройте проект в выбранном вами редакторе.
- Следуйте инструкциям «Запустить приложение» в разделе «Начало работы: тест-драйв» для выбранного вами редактора.
Успех! На вашем устройстве вы должны увидеть страницу входа в Shrine из предыдущих тестов кода.
Андроид | iOS |
Нажмите «Далее», чтобы увидеть страницу продукта.
Андроид | 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 2014 года .)
Редактор тем материалов сгруппировал их по оттенкам с числовой маркировкой, включая метки от 50, 100, 200 до 900 каждого цвета. Shrine использует только оттенки 50, 100 и 300 из розового образца и 900 из коричневого.
Каждый цветной параметр виджета сопоставлен с цветом из этих схем. Например, цвет оформления текстового поля, когда оно активно принимает вводимые данные, должен быть основным цветом темы. Если этот цвет недоступен (его легко увидеть на фоне), используйте вместо него другой цвет.
Теперь, когда у нас есть цвета, которые мы хотим использовать, мы можем применить их к пользовательскому интерфейсу. Мы сделаем это, установив значения виджета 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
Сохраните проект. Теперь ваш экран входа в систему должен выглядеть так:
Андроид | iOS |
5. Измените типографику и стили меток.
Помимо изменения цвета, дизайнер также предоставил нам специальную типографику. ThemeData Flutter включает в себя 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, если вы скопируете и вставите приведенное выше объявление. Если вы получаете ошибки, начните с удаления начальных пробелов и замены их пробелами, используя отступ в два пробела. (Два пробела перед
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,
),
Сохраните проект. На этот раз также перезапустите приложение (так называемый « Горячий перезапуск »), поскольку мы изменили шрифты.
Андроид | iOS |
Текст на главном экране и на главном экране выглядит по-разному: часть текста использует шрифт 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,
Сохраните проект.
Андроид | iOS |
Это выглядит намного лучше.
Тема для текстовых полей
Вы также можете оформить тематическое оформление текстовых полей с помощью InputDecorationTheme .
В app.dart
в методе _buildShrineTheme()
укажите значение inputDecorationTheme:
// 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,
),
Горячий перезапуск. Ваш экран входа в систему должен выглядеть следующим образом, когда поле «Имя пользователя» активно (когда вы его вводите):
Андроид | iOS |
Введите текст в текстовое поле — границы и плавающие метки отображаются в основном цвете. Но нам не так легко это увидеть. Он недоступен для людей, у которых есть проблемы с различением пикселей с недостаточно высоким цветовым контрастом. (Дополнительную информацию см. в статье «Рекомендации по использованию материалов: цвет и доступность ».)
В 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,
),
),
Сохраните проект.
Андроид | iOS |
6. Отрегулируйте высоту
Теперь, когда вы придали странице определенный цвет и типографику, соответствующую Shrine, давайте отрегулируем высоту.
Измените высоту кнопки ДАЛЕЕ
По умолчанию для ElevatedButton
установлено значение 2. Давайте поднимем его выше.
В login.dart
добавьте значение style:
к NEXT ElevatedButton:
ElevatedButton(
child: const Text('NEXT'),
onPressed: () {
Navigator.pop(context);
},
style: ElevatedButton.styleFrom(
foregroundColor: kShrineBrown900,
backgroundColor: kShrinePink100,
elevation: 8.0,
),
),
Сохраните проект.
Андроид | iOS |
Отрегулируйте высоту карты
Прямо сейчас карточки лежат на белой поверхности рядом с навигацией сайта.
В home.dart
добавьте значение elevation:
к Cards:
// TODO: Adjust card heights (103)
elevation: 0.0,
Сохраните проект.
Андроид | iOS |
Вы удалили тень под картами.
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
. Это остается вызовом для ученика!
Горячий перезапуск.
Андроид | iOS |
8. Измените макет
Далее давайте изменим макет, чтобы отображать карточки с разными пропорциями и размерами, чтобы каждая карточка выглядела уникально по сравнению с другими.
Замените GridView на AsymmetricView.
Мы уже написали файлы для асимметричной компоновки.
В home.dart
добавьте следующий импорт:
import 'supplemental/asymmetric_view.dart';
Удалите _buildGridCards
и замените body
:
body: AsymmetricView(
products: ProductsRepository.loadProducts(Category.all),
),
Сохраните проект.
Андроид | iOS |
Теперь товары прокручиваются горизонтально в тканом узоре.
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,
),
),
);
}
Горячий перезапуск. Теперь должна появиться новая тема.
Андроид | iOS |
Андроид | iOS |
Результат совсем другой! Давайте вернем _buildShrineTheme
app.dart's
к тому состоянию, которое было до этого шага. Или загрузите стартовый код 104.
10. Поздравляем!
К этому моменту вы создали приложение, которое соответствует спецификациям вашего дизайнера.
Следующие шаги
Теперь вы использовали следующий Material Flutter: тему, типографику, высоту и форму. Вы можете изучить больше компонентов и подсистем в библиотеке Material Flutter.
Покопайтесь в файлах в supplemental
каталоге, чтобы узнать, как мы создали асимметричную сетку макета с горизонтальной прокруткой.
Что делать, если запланированный дизайн вашего приложения содержит элементы, у которых нет компонентов в библиотеке? В MDC-104: Расширенные компоненты материалов мы показываем, как создавать пользовательские компоненты с использованием библиотеки Material Flutter для достижения желаемого вида.