Flutter для разработчиков React Native¶
Этот документ предназначен для разработчиков React Native (RN), желающих применить имеющиеся знания о RN для создания мобильных приложений на Flutter. Если вы понимаете основы фреймворка RN, то можете использовать этот документ как способ начать изучение разработки на Flutter.
Этот документ можно использовать в качестве "поваренной книги", переходя от одного вопроса к другому и находя вопросы, наиболее соответствующие вашим потребностям.
Введение в Dart для разработчиков JavaScript (ES6)¶
Как и React Native, Flutter использует представления в реактивном стиле. Однако если RN транспилируется в нативные виджеты, то Flutter компилируется полностью в нативный код. Flutter управляет каждым пикселем на экране, что позволяет избежать проблем с производительностью, связанных с необходимостью использования моста JavaScript.
Dart - простой в изучении язык, обладающий следующими возможностями:
- Открытый масштабируемый язык программирования для создания веб-приложений, серверов и мобильных приложений.
- Объектно-ориентированный язык с единым наследованием, использующий синтаксис в стиле C, который AOT-компилируется в native.
- Опционально транскомпилируется в JavaScript.
- Поддерживает интерфейсы и абстрактные классы.
Ниже приведены несколько примеров различий между JavaScript и Dart.
Точка входа¶
В JavaScript нет предопределенной функции входа — точку входа определяете вы.
Javascript | |
---|---|
1 2 3 |
|
В Dart каждое приложение должно иметь функцию верхнего уровня main()
, которая служит точкой входа в приложение.
Dart | |
---|---|
1 |
|
Попробуйте это сделать в DartPad.
Печать в консоль¶
Для печати на консоль в Dart используется функция print()
.
Javascript | |
---|---|
1 |
|
Dart | |
---|---|
1 |
|
Попробуйте это сделать в DartPad.
Переменные¶
Dart безопасен для типов — он использует комбинацию статической проверки типов и проверок во время выполнения, чтобы гарантировать, что значение переменной всегда соответствует ее статическому типу. Хотя типы являются обязательными, некоторые аннотации типов являются необязательными, поскольку Dart выполняет вывод типов.
Создание и присвоение переменных¶
В JavaScript переменные не могут быть типизированы.
В Dart переменные должны быть либо явно типизированы, либо система типов должна автоматически выводить нужный тип.
Javascript | |
---|---|
1 |
|
Dart | |
---|---|
1 2 3 |
|
Попробуйте это сделать в DartPad.
Более подробную информацию можно найти в разделе Dart's Type System.
Значение по умолчанию¶
В JavaScript неинициализированные переменные имеют значение undefined
.
В Dart неинициализированные переменные имеют начальное значение null
. Поскольку в Dart числа являются объектами, то даже неинициализированные переменные с числовыми типами имеют значение null
.
Начиная с версии 2.12, Dart поддерживает Sound Null Safety, все базовые типы по умолчанию являются ненулевыми, которые должны быть инициализированы как ненулевое значение.
Javascript | |
---|---|
1 |
|
Dart | |
---|---|
1 2 |
|
Попробуйте это сделать в DartPad.
Для получения дополнительной информации см. документацию по variables.
Проверка на наличие null или нуля¶
В JavaScript при использовании оператора сравнения ==
значения 1 или любые ненулевые объекты рассматриваются как true
.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 |
|
В Dart только булево значение true
рассматривается как истина.
Dart | |
---|---|
1 2 3 4 5 |
|
Попробуйте это сделать в DartPad.
Функции¶
Функции Dart и JavaScript в целом похожи. Основное различие заключается в объявлении.
Javascript | |
---|---|
1 2 3 |
|
Dart | |
---|---|
1 2 3 4 |
|
Попробуйте это сделать в DartPad.
Для получения дополнительной информации см. документацию по functions.
Асинхронное программирование¶
Futures¶
Как и JavaScript, Dart поддерживает однопоточное выполнение. В JavaScript объект Promise
представляет возможное завершение (или неудачу) асинхронной операции и ее результирующее значение.
В Dart для этого используются объекты Future.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Для получения дополнительной информации см. документацию по объектам Future.
async
и await
¶
Объявление функции async
определяет асинхронную функцию.
В JavaScript функция async
возвращает Promise
. Оператор await
используется для ожидания Promise
.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
В Dart функция async
возвращает Future
, а тело функции планируется к выполнению позже. Оператор await
используется для ожидания Future
.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
Более подробную информацию можно найти в документации по async and await.
Основы¶
Как создать приложение на Flutter?¶
Чтобы создать приложение с использованием React Native, необходимо выполнить команду create-react-native-app
из командной строки.
1 |
|
Чтобы создать приложение на Flutter, выполните одно из следующих действий:
- Используйте IDE с установленными плагинами Flutter и Dart.
- Используйте команду
flutter create
из командной строки. Убедитесь, что Flutter SDK находится в PATH.
1 |
|
Для получения дополнительной информации см. раздел Getting started, в котором рассказывается о создании приложения-счетчика нажатий на кнопки. При создании проекта Flutter собираются все файлы, необходимые для запуска примера приложения на устройствах Android и iOS.
Как запустить приложение?¶
В React Native вы запускаете команду npm run
или yarn run
из каталога проекта.
Запускать приложения Flutter можно несколькими способами:
- Использовать опцию "run" в IDE с плагинами Flutter и Dart.
- Использовать команду
flutter run
из корневого каталога проекта.
Приложение запускается на подключенном устройстве, симуляторе iOS или эмуляторе Android.
Дополнительную информацию можно найти в документации Flutter Getting started.
Как импортировать виджеты?¶
В React Native необходимо импортировать каждый требуемый компонент.
Javascript | |
---|---|
1 2 3 |
|
Во Flutter для использования виджетов из библиотеки Material Design импортируйте пакет material.dart
. Для использования виджетов в стиле iOS импортируйте библиотеку Cupertino. Для использования более базового набора виджетов импортируйте библиотеку Widgets. Также можно написать собственную библиотеку виджетов и импортировать ее.
Dart | |
---|---|
1 2 3 4 |
|
Какой бы пакет виджетов вы ни импортировали, Dart берет только те виджеты, которые используются в вашем приложении.
Для получения дополнительной информации см. Flutter Widget Catalog.
Что является эквивалентом приложения React Native "Hello world!" во Flutter?¶
В React Native класс HelloWorldApp
расширяет React.Component
и реализует метод render, возвращая компонент представления.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Во Flutter можно создать идентичное приложение "Hello world!", используя виджеты Center
и Text
из основной библиотеки виджетов. Виджет Center
становится корнем дерева виджетов и имеет один дочерний виджет Text
.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
На следующих изображениях показан пользовательский интерфейс для Android и iOS для базового приложения Flutter "Hello world!".
Теперь, когда вы познакомились с самым базовым приложением Flutter, в следующем разделе мы покажем, как использовать преимущества богатых библиотек виджетов Flutter для создания современного, отполированного приложения.
Как использовать виджеты и вложить их в дерево виджетов?¶
Во Flutter почти все является виджетами.
Виджеты являются основными элементами пользовательского интерфейса приложения. Виджеты объединяются в иерархию, называемую деревом виджетов. Каждый виджет вложен в родительский виджет и наследует свойства от родительского. Даже сам объект приложения является виджетом. Отдельного объекта "приложение" не существует. Вместо него эту роль выполняет корневой виджет.
Виджет может определять:
- структурный элемент, например, кнопку или меню
- стилистический элемент, например, шрифт или цветовую схему
- Аспект компоновки, например, подгонку или выравнивание.
В следующем примере показано приложение "Hello world!", использующее виджеты из библиотеки Material. В этом примере дерево виджетов вложено внутрь корневого виджета MaterialApp
.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
На следующих изображениях показан "Hello world!", построенный на основе виджетов Material Design. Бесплатно вы получаете больше функциональности, чем в базовом приложении "Hello world!".
При написании приложения вы будете использовать два типа виджетов: [StatelessWidget
][] или [StatefulWidget
][]. Виджет StatelessWidget
- это то, что он означает — виджет без состояния. Виджет StatelessWidget
создается один раз и никогда не меняет своего вида. Виджет StatefulWidget
динамически изменяет свое состояние в зависимости от получаемых данных или ввода пользователя.
Важным отличием виджетов без состояния от виджетов с состоянием является то, что у виджетов с состоянием есть объект State
, который хранит данные о состоянии и переносит их при перестройке дерева, так что они не теряются.
В простых или базовых приложениях легко вложить виджеты, но по мере расширения кодовой базы и усложнения приложения следует разбивать глубоко вложенные виджеты на функции, возвращающие виджет или более мелкие классы. Создание отдельных функций и виджетов позволяет повторно использовать компоненты внутри приложения.
Как создавать многократно используемые компоненты?¶
В React Native для создания многоразового компонента необходимо определить класс, а затем использовать методы props
для установки или возврата свойств и значений выбранных элементов. В приведенном ниже примере определяется класс CustomCard
, который затем используется внутри родительского класса.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Во Flutter можно определить класс для создания пользовательского виджета, а затем использовать его повторно. Можно также определить и вызвать функцию, возвращающую многократно используемый виджет, как это показано в функции build
в следующем примере.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
|
В предыдущем примере конструктор класса CustomCard
использует синтаксис фигурных скобок Dart { }
для указания named parameters.
Чтобы затребовать эти поля, нужно либо убрать фигурные скобки из конструктора, либо добавить в конструктор required
.
На следующих скриншотах показан пример многократно используемого класса CustomCard
.
Структура проекта и ресурсы¶
С чего начать написание кода?¶
Начните с файла lib/main.dart
. Он автоматически генерируется при создании приложения Flutter.
Dart | |
---|---|
1 2 3 |
|
Во Flutter точкой входа является файл {project_name}/lib/main.dart
, а выполнение начинается с функции main
.
Как структурированы файлы в приложении Flutter?¶
При создании нового проекта Flutter формирует следующую структуру каталогов. В дальнейшем ее можно изменить, но начинать следует именно с нее.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Где я размещаю свои ресурсы и активы и как их использовать?¶
Ресурс или актив Flutter - это файл, который поставляется и развертывается вместе с вашим приложением и доступен во время выполнения. Приложения Flutter могут включать следующие типы активов:
- Статические данные, такие как файлы JSON
- файлы конфигурации
- Значки и изображения (JPEG, PNG, GIF, анимированный GIF, WebP, анимированный WebP, BMP и WBMP).
Для определения активов, необходимых приложению, Flutter использует файл pubspec.yaml
, расположенный в корне проекта.
1 2 3 4 |
|
В подразделе assets
указываются файлы, которые должны быть включены в приложение. Каждый актив идентифицируется явным путем относительно файла pubspec.yaml
, в котором находится файл актива. Порядок объявления активов не имеет значения. Не имеет значения и фактический используемый каталог (в данном случае assets
). Однако, хотя активы могут быть размещены в любом каталоге приложения, лучше всего размещать их в каталоге assets
.
Во время сборки Flutter помещает активы в специальный архив, называемый asset bundle, из которого приложения считывают их во время выполнения. Когда путь к активу указан в секции assets в файле pubspec.yaml
, процесс сборки ищет все файлы с таким же именем в соседних подкаталогах. Эти файлы также включаются в пакет активов вместе с указанным активом. Flutter использует варианты активов при выборе подходящих по разрешению изображений для вашего приложения.
В React Native для добавления статического изображения необходимо поместить файл изображения в каталог с исходным кодом и сослаться на него.
Javascript | |
---|---|
1 2 3 4 5 6 7 |
|
Во Flutter добавление статического изображения в приложение осуществляется с помощью конструктора Image.asset
в методе сборки виджета.
Dart | |
---|---|
1 |
|
Более подробную информацию см. Adding Assets and Images in Flutter.
Как загружать изображения по сети?¶
В React Native необходимо указать uri
в свойстве source
компонента Image
, а также указать размер, если это необходимо.
Во Flutter для включения изображения из URL используйте конструктор Image.network
.
Dart | |
---|---|
1 |
|
Как устанавливать пакеты и плагины пакетов?¶
Flutter поддерживает использование общих пакетов, предоставленных другими разработчиками экосистем Flutter и Dart. Это позволяет быстро создать приложение без необходимости разрабатывать все с нуля. Пакеты, содержащие код, специфичный для конкретной платформы, называются плагинами пакетов.
В React Native для установки пакетов из командной строки используется команда yarn add {package-name}
или npm install --save {package-name}
.
Во Flutter установка пакета выполняется по следующей инструкции:
-
Чтобы добавить пакет
google_sign_in
в качестве зависимости, выполните командуflutter pub add
:1
$ flutter pub add google_sign_in
-
Установите пакет из командной строки с помощью команды
flutter pub get
. Если вы используете IDE, она часто запускаетflutter pub get
за вас, или может предложить вам сделать это. -
Импортируйте пакет в код вашего приложения, как показано ниже:
Dart 1
import 'package:flutter/material.dart';
Более подробная информация приведена в разделах Using Packages и Developing Packages & Plugins.
Многие пакеты, совместно используемые разработчиками Flutter, можно найти в разделе Flutter packages в pub.dev.
Виджеты Flutter¶
Во Flutter пользовательский интерфейс строится из виджетов, которые описывают, как должно выглядеть их представление с учетом текущей конфигурации и состояния.
Виджеты часто состоят из множества небольших, одноцелевых виджетов, которые вложены друг в друга для получения мощных эффектов. Например, виджет Container
состоит из нескольких виджетов, отвечающих за компоновку, рисование, позиционирование и размер. В частности, виджет Container
включает в себя виджеты LimitedBox
, ConstrainedBox
, Align
, Padding
, DecoratedBox
и Transform
. Вместо того чтобы создавать подкласс Container
для получения индивидуального эффекта, можно компоновать эти и другие простые виджеты новыми и уникальными способами.
Виджет Center
- еще один пример того, как можно управлять расположением. Чтобы выровнять виджет по центру, оберните его виджетом Center
, а затем используйте виджеты компоновки для выравнивания, строк, столбцов и сеток. Эти виджеты компоновки не имеют собственного визуального представления. Их единственное назначение - управление некоторыми аспектами компоновки другого виджета. Чтобы понять, почему виджет отображается определенным образом, часто бывает полезно просмотреть соседние виджеты.
Более подробную информацию можно найти в Flutter Technical Overview.
Для получения дополнительной информации о базовых виджетах из пакета Widgets
смотрите Flutter Basic Widgets, Flutter Widget Catalog или Flutter Widget Index.
Views¶
Что является эквивалентом контейнера View
?¶
В React Native View
- это контейнер, который поддерживает компоновку с помощью Flexbox
, стиль, обработку касаний и элементы управления доступностью.
Во Flutter можно использовать основные виджеты компоновки из библиотеки Widgets
, такие как [Container
][], [Column
][], [Row
][] и [Center
][]. Для получения дополнительной информации см. каталог Layout Widgets.
Что является эквивалентом FlatList
или SectionList
?¶
Список List
- это прокручиваемый список компонентов, расположенных вертикально.
В React Native для отображения простых или секционированных списков используются FlatList
или SectionList
.
Javascript | |
---|---|
1 2 3 4 5 |
|
[ListView
][] - наиболее часто используемый во Flutter виджет прокрутки. Конструктор по умолчанию принимает явный список дочерних элементов. [ListView
][] наиболее подходит для небольшого числа виджетов. Для большого или бесконечного списка используйте ListView.builder
, который строит дочерние элементы по требованию и создает только те из них, которые видны.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 |
|
О том, как реализовать бесконечную прокрутку списка, можно узнать из официального примера infinite_list
.
Как использовать Canvas для рисования или раскрашивания?¶
В React Native компоненты canvas отсутствуют, поэтому используются сторонние библиотеки типа react-native-canvas
.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Во Flutter для рисования на холсте можно использовать классы [CustomPaint
][] и [CustomPainter
][].
В следующем примере показано, как рисовать на этапе закрашивания с помощью виджета CustomPaint
. Он реализует абстрактный класс CustomPainter
и передает его в свойство painter виджета CustomPaint
. Подклассы CustomPaint
должны реализовывать методы paint()
и shouldRepaint()
.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
Макеты¶
Как использовать виджеты для определения свойств макета?¶
В React Native большая часть компоновки может быть выполнена с помощью реквизитов, которые передаются конкретному компоненту. Например, можно использовать реквизит style
для компонента View
, чтобы задать свойства flexbox. Чтобы расположить компоненты в столбец, можно указать такой реквизит, как: flexDirection: 'column'
.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 9 |
|
Во Flutter компоновка определяется в основном виджетами, специально предназначенными для компоновки, в сочетании с виджетами управления и их стилевыми свойствами.
Например, виджеты [Column
][] и [Row
][] принимают массив дочерних элементов и выравнивают их по вертикали и горизонтали соответственно. Виджет [Container
][] принимает комбинацию свойств макета и стиля, а виджет [Center
][] центрирует свои дочерние виджеты.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Flutter предоставляет множество виджетов компоновки в своей основной библиотеке виджетов. Например, [Padding
][], [Align
][] и [Stack
][].
Полный список приведен в разделе Layout Widgets.
Как накладывать слои на виджеты?¶
В React Native компоненты можно располагать слоями, используя absolute
позиционирование.
Flutter использует виджет [Stack
][] для расположения дочерних виджетов слоями. Виджеты могут полностью или частично перекрывать базовый виджет.
Виджет Stack
позиционирует свои дочерние виджеты относительно краев своего поля. Этот класс полезен, если необходимо просто наложить несколько дочерних виджетов друг на друга.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
В предыдущем примере Stack
используется для наложения контейнера (который отображает свой Text
на полупрозрачном черном фоне) поверх CircleAvatar
. Стек смещает текст с помощью свойства выравнивания и координат Alignment
.
Для получения дополнительной информации см. документацию по классу [Stack
][].
Стилизация¶
Как стилизовать компоненты?¶
В React Native для стилизации компонентов используются встроенная стилизация и stylesheets.create
.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Во Flutter виджет Text
может принимать класс TextStyle
для своего свойства style. Если вы хотите использовать один и тот же стиль текста в нескольких местах, вы можете создать класс [TextStyle
][] и использовать его для нескольких виджетов Text
.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Как использовать Icons
и Colors
?¶
В React Native нет поддержки иконок, поэтому используются сторонние библиотеки.
Во Flutter импорт библиотеки Material также позволяет получить богатый набор Material icons и colors.
Dart | |
---|---|
1 |
|
При использовании класса Icons
обязательно установите значение uses-material-design: true
в файле проекта pubspec.yaml
. Это гарантирует, что шрифт MaterialIcons
, отображающий иконки, будет включен в ваше приложение. В общем случае, если вы собираетесь использовать библиотеку Material, вам следует включить эту строку.
1 2 3 |
|
Пакет Flutter Cupertino (iOS-style) обеспечивает высокую точность виджетов для текущего языка дизайна iOS. Чтобы использовать шрифт CupertinoIcons
, добавьте зависимость для cupertino_icons
в файл pubspec.yaml
вашего проекта.
1 2 3 |
|
Чтобы глобально настроить цвета и стили компонентов, используйте ThemeData
для задания цветов по умолчанию для различных аспектов темы. Установите свойство theme в MaterialApp
на объект ThemeData
. Класс [Colors
][] предоставляет цвета из color palette Material Design.
В следующем примере для основного образца устанавливается blue
, а для выделения текста - red
.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Как добавить темы стилей?¶
В React Native общие темы задаются для компонентов в таблицах стилей и затем используются в компонентах.
Во Flutter можно создать единый стиль практически для всего, определив стиль в классе [ThemeData
][] и передав его в свойство theme в виджете [MaterialApp
][].
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 |
|
Применять Theme
можно даже без использования виджета MaterialApp
. Виджет [Theme
][] принимает ThemeData
в параметре data
и применяет ThemeData
ко всем своим дочерним виджетам.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Управление состоянием¶
Состояние - это информация, которая может быть прочитана синхронно при создании виджета, или информация, которая может измениться в течение времени жизни виджета. Для управления состоянием приложения во Flutter используется [StatefulWidget
][] в паре с объектом State.
Более подробную информацию о способах управления состоянием во Flutter можно найти в разделе State management.
StatelessWidget¶
Виджет StatelessWidget
во Flutter - это виджет, который не требует изменения состояния — у него нет внутреннего состояния, которым можно управлять.
Виджеты без состояния полезны, когда описываемая часть пользовательского интерфейса не зависит ни от чего, кроме конфигурационной информации самого объекта и [BuildContext
][], в котором раздувается виджет.
AboutDialog, [CircleAvatar
][] и [Text
][] являются примерами виджетов без статусов, подклассом которых является [StatelessWidget
][].
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
В предыдущем примере конструктор класса MyStatelessWidget
использует для передачи text
, который помечен как final
. Этот класс расширяет класс StatelessWidget
— он содержит неизменяемые данные.
Метод build
виджета stateless обычно вызывается только в трех ситуациях:
- При вставке виджета в дерево
- Когда родитель виджета изменяет свою конфигурацию
- когда изменяется [
InheritedWidget
][], от которого он зависит.
StatefulWidget¶
Виджет [StatefulWidget
][] - это виджет, который изменяет состояние. Для управления изменением состояния виджета StatefulWidget
используйте метод setState
. Вызов setState()
сообщает фреймворку Flutter, что в состоянии что-то изменилось, что заставляет приложение повторно выполнить метод build()
, чтобы отразить изменения.
State - это информация, которая может быть прочитана синхронно при сборке виджета и может измениться в течение его жизни. Реализатор виджета обязан обеспечить своевременное уведомление объекта state об изменении состояния. Используйте StatefulWidget
, если состояние виджета может изменяться динамически. Например, состояние виджета изменяется при вводе текста в форму или перемещении ползунка. Или оно может меняться с течением времени - например, при обновлении данных в пользовательском интерфейсе.
[Checkbox
][], [Radio
][], [Slider
][], [InkWell
][], [Form
][] и [TextField
][] - это примеры виджетов с состоянием, которые являются подклассами [StatefulWidget
][].
В следующем примере объявлен виджет StatefulWidget
, для которого требуется метод createState()
. Этот метод создает объект состояния, управляющий состоянием виджета, _MyStatefulWidgetState
.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 |
|
Следующий класс состояния, _MyStatefulWidgetState
, реализует метод build()
для виджета. При изменении состояния, например, при переключении пользователем кнопки, вызывается setState()
с новым значением toggle. Это заставляет фреймворк перестроить данный виджет в пользовательском интерфейсе.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
|
Каковы лучшие практики использования StatefulWidget и StatelessWidget?¶
Вот несколько моментов, которые следует учитывать при проектировании виджета.
-
Определите, должен ли виджет быть
StatefulWidget
илиStatelessWidget
.Во Flutter виджеты являются либо Stateful, либо Stateless - в зависимости от того, зависят ли они от изменения состояния.
-
Если виджет изменяется — пользователь взаимодействует с ним или поток данных прерывает работу пользовательского интерфейса, то он является Stateful.
-
Если виджет конечный или неизменяемый, то он Stateless.
-
-
Определите, какой объект управляет состоянием виджета (для
StatefulWidget
).Во Flutter существует три основных способа управления состоянием:
- Виджет управляет своим собственным состоянием
- Родительский виджет управляет состоянием виджета
- Комбинированный подход
Решая, какой подход использовать, учитывайте следующие принципы:
- Если состояние - это пользовательские данные, например, установленный или снятый флажок или положение ползунка, то лучше всего управлять состоянием родительского виджета.
- Если рассматриваемое состояние является эстетическим, например анимация, то лучше всего управлять этим состоянием самому виджету.
- Если есть сомнения, пусть родительский виджет управляет состоянием дочернего виджета.
-
Подкласс StatefulWidget и State.
Класс
MyStatefulWidget
управляет собственным состоянием — он расширяетStatefulWidget
, переопределяет методcreateState()
для создания объектаState
, а фреймворк вызываетcreateState()
для создания виджета. В данном примереcreateState()
создает экземпляр_MyStatefulWidgetState
, который реализуется в следующей лучшей практике.Dart 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
class MyStatefulWidget extends StatefulWidget { const MyStatefulWidget({ super.key, required this.title, }); final String title; @override State<MyStatefulWidget> createState() => _MyStatefulWidgetState(); } class _MyStatefulWidgetState extends State<MyStatefulWidget> { @override Widget build(BuildContext context) { //... } }
-
Добавьте StatefulWidget в дерево виджетов.
Добавьте свой собственный
StatefulWidget
в дерево виджетов в методе сборки приложения.Dart 1 2 3 4 5 6 7 8 9 10 11 12
class MyStatelessWidget extends StatelessWidget { // This widget is the root of your application. const MyStatelessWidget({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( title: 'Flutter Demo', home: MyStatefulWidget(title: 'State Change Demo'), ); } }
Props¶
В React Native большинство компонентов можно настраивать при их создании с помощью различных параметров или свойств, называемых props
. Эти параметры могут быть использованы в дочернем компоненте с помощью this.props
.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
|
Во Flutter свойству, полученному в параметризованном конструкторе, присваивается локальная переменная или функция с пометкой final
.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
|
Локальное хранилище¶
Если вам не нужно хранить много данных, и они не требуют структурирования, вы можете использовать shared_preferences
, которая позволяет читать и записывать постоянные пары ключ-значение примитивных типов данных: booleans, floats, ints, longs и strings.
Как хранить постоянные пары ключ-значение, которые являются глобальными для приложения?¶
В React Native для хранения и извлечения данных, которые являются постоянными и глобальными для приложения, используются функции setItem
и getItem
компонента AsyncStorage
.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Во Flutter для хранения и получения данных с ключевыми значениями, которые являются постоянными и глобальными для приложения, используется плагин [shared_preferences
][]. Плагин shared_preferences
оборачивает NSUserDefaults
на iOS и SharedPreferences
на Android, обеспечивая постоянное хранение простых данных.
Чтобы добавить пакет shared_preferences
в качестве зависимости, выполните команду flutter pub add
:
1 |
|
Dart | |
---|---|
1 |
|
Для реализации постоянных данных следует использовать методы-установщики, предоставляемые классом SharedPreferences
. Методы setter доступны для различных примитивных типов, таких как setInt
, setBool
и setString
. Для чтения данных используется соответствующий метод getter, предоставляемый классом SharedPreferences
. Для каждого сеттера существует соответствующий метод геттера, например, getInt
, getBool
и getString
.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 |
|
Маршрутизация¶
Большинство приложений содержит несколько экранов для отображения различных типов информации. Например, у вас может быть экран продукта, на котором отображаются изображения, где пользователи могут нажать на изображение продукта, чтобы получить более подробную информацию о нем на новом экране.
В Android новые экраны - это новые Activities. В iOS новые экраны - это новые ViewControllers. Во Flutter экраны - это просто виджеты! А для перехода к новым экранам во Flutter используется виджет Navigator.
Как мне перемещаться между экранами?¶
В React Native есть три основных навигатора: StackNavigator, TabNavigator и DrawerNavigator. Каждый из них предоставляет возможность конфигурирования и определения экранов.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Во Flutter существует два основных виджета, используемых для навигации между экранами:
- [
Route
][] - это абстракция для экрана или страницы приложения. - Виджет [
Navigator
][] - это виджет, который управляет маршрутами.
Виджет Navigator
определяется как виджет, управляющий набором дочерних виджетов с дисциплиной стека. Навигатор управляет стеком объектов Route
и предоставляет методы для управления стеком, такие как [Navigator.push
][] и [Navigator.pop
][]. Список маршрутов может быть задан в виджете [MaterialApp
][], или они могут быть построены "на лету", например, в анимации героя. В следующем примере именованные маршруты задаются в виджете MaterialApp
.
Именованные маршруты больше не рекомендуются для большинства приложений. Дополнительную информацию см. в разделе Limitations на странице navigation overview.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Для перехода к именованному маршруту используется метод [Navigator.of()
][], в котором указывается BuildContext
(дескриптор расположения виджета в дереве виджетов). Имя маршрута передается в функцию pushNamed
для перехода к указанному маршруту.
Dart | |
---|---|
1 |
|
Можно также использовать метод push функции Navigator
, который добавляет заданный [Route
][] в историю навигатора, наиболее плотно охватывающего заданный [BuildContext
][], и осуществляет переход к нему. В следующем примере виджет [MaterialPageRoute
][] представляет собой модальный маршрут, который заменяет весь экран с помощью адаптивного к платформе перехода. В качестве обязательного параметра он принимает [WidgetBuilder
][].
Dart | |
---|---|
1 2 3 4 5 6 |
|
Как использовать навигацию по вкладкам и по ящикам?¶
В приложениях Material Design есть два основных варианта навигации Flutter: вкладки и ящики. Когда места для вкладок недостаточно, хорошей альтернативой являются ящики.
Навигация по вкладкам¶
В React Native для отображения вкладок и навигации по вкладкам используются функции createBottomTabNavigator
и TabNavigation
.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 9 10 |
|
Flutter предоставляет несколько специализированных виджетов для навигации по ящикам и вкладкам:
- [
TabController
][] - Координирует выбор вкладок между
TabBar
иTabBarView
иTabBarView
. - [
TabBar
][] - Отображает горизонтальный ряд вкладок.
- [
Tab
][] - Создает вкладку
TabBar
с материальным дизайном. - [
TabBarView
][] - Отображает виджет, соответствующий текущей выбранной вкладке.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Контроллер TabController
необходим для координации выбора вкладок между TabBar
и TabBarView
. Аргумент length
конструктора TabController
- это общее количество вкладок. Для запуска уведомления при изменении состояния кадра требуется TickerProvider
. В качестве TickerProvider
выступает vsync
. Передавайте аргумент vsync: this
конструктору TabController
каждый раз, когда создаете новый TabController
.
[TickerProvider
][] - это интерфейс, реализуемый классами, которые могут продавать объекты [Ticker
][]. Тикеры могут использоваться любым объектом, который должен получать уведомления о срабатывании кадра, но чаще всего они используются опосредованно через [AnimationController
][]. Для получения своего Ticker
контроллеру анимации необходим TickerProvider
. Если вы создаете AnimationController из состояния, то для получения подходящего TickerProvider
можно использовать классы [TickerProviderStateMixin
][] или [SingleTickerProviderStateMixin
][].
Виджет [Scaffold
][] оборачивает новый виджет TabBar
и создает две вкладки. Виджет TabBarView
передается в качестве параметра body
виджета Scaffold
. Все экраны, соответствующие вкладкам виджета TabBar
, являются дочерними для виджета TabBarView
вместе с тем же TabController
.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
Drawer navigation¶
В React Native импортируйте необходимые пакеты react-navigation, а затем используйте createDrawerNavigator
и DrawerNavigation
.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 9 |
|
Во Flutter мы можем использовать виджет Drawer
в сочетании с Scaffold
для создания макета с ящиком Material Design. Чтобы добавить виджет Drawer
в приложение, оберните его виджетом Scaffold
. Виджет Scaffold
обеспечивает согласованную визуальную структуру приложений, которые следуют рекомендациям Material Design. Он также поддерживает специальные компоненты Material Design, такие как Drawers
, AppBars
и SnackBars
.
Виджет Drawer
- это панель Material Design, которая выдвигается горизонтально от края Scaffold
для отображения навигационных ссылок в приложении. В качестве дочернего виджета Drawer
можно предоставить [ElevatedButton
][], виджет [Text
][] или список элементов для отображения. В следующем примере виджет [ListTile
][] обеспечивает навигацию при касании.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Виджет Scaffold
также включает в себя виджет AppBar
, который автоматически отображает соответствующую кнопку IconButton для показа Drawer
, когда Drawer доступен в Scaffold
. Виджет Scaffold
автоматически обрабатывает жест пролистывания края, чтобы показать Drawer
.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Обнаружение жестов и обработка событий касания¶
Для обнаружения жестов и реагирования на них Flutter поддерживает касания, перетаскивания и масштабирование. Система жестов во Flutter состоит из двух отдельных уровней. Первый слой включает необработанные события указателей, которые описывают расположение и перемещение указателей (например, прикосновения, движения мыши или стилуса) по экрану. Второй слой включает жесты, которые описывают семантические действия, состоящие из одного или нескольких движений указателя.
Как добавить в виджет слушателей нажатия или щелчка?¶
В React Native слушатели добавляются к компонентам с помощью PanResponder
или компонентов Touchable
.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 |
|
Для более сложных жестов и объединения нескольких касаний в один жест используется [PanResponder
][].
Javascript | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
Во Flutter для добавления слушателя щелчков (или нажатий) в виджет используйте кнопку или сенсорный виджет, имеющий onPress: field
. Или добавьте обнаружение жестов к любому виджету, обернув его в [GestureDetector
][].
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
Более подробную информацию, включая список обратных вызовов Flutter GestureDetector
, можно найти в разделе GestureDetector class.
Выполнение сетевых запросов HTTP¶
Получение данных из Интернета является обычным делом для большинства приложений. И во Flutter пакет http
предоставляет самый простой способ получения данных из Интернета.
Как получить данные из вызовов API?¶
React Native предоставляет Fetch API для работы с сетью - вы делаете fetch-запрос, а затем получаете ответ, чтобы получить данные.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Flutter использует пакет http
.
Чтобы добавить пакет http
в качестве зависимости, выполните команду flutter pub add
:
1 |
|
Flutter использует клиент поддержки HTTP [dart:io
][] ядра. Чтобы создать HTTP-клиент, импортируйте dart:io
.
Dart | |
---|---|
1 |
|
Клиент поддерживает следующие операции HTTP: GET, POST, PUT и DELETE.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Ввод формы¶
Текстовые поля позволяют пользователям вводить текст в ваше приложение, поэтому их можно использовать для создания форм, приложений для обмена сообщениями, поиска и т.д. Flutter предоставляет два основных виджета текстовых полей: [TextField
][] и [TextFormField
][].
Как использовать виджеты текстовых полей?¶
В React Native для ввода текста используется компонент TextInput
, который отображает поле ввода текста, а затем с помощью обратного вызова сохраняет значение в переменной.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 |
|
Во Flutter для управления виджетом TextField
используется класс [TextEditingController
][]. При каждом изменении текстового поля контроллер уведомляет своих слушателей.
Слушатели считывают свойства text и selection, чтобы узнать, что пользователь ввел в поле. Доступ к тексту в TextField
можно получить через свойство text
контроллера.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
В данном примере при нажатии пользователем кнопки submit диалог оповещения отображает текущий текст, введенный в текстовое поле. Для этого используется виджет [AlertDialog
][], который выводит сообщение о предупреждении, а доступ к тексту из TextField
осуществляется через свойство text
контроллера [TextEditingController
][].
Как использовать виджеты формы?¶
Во Flutter используется виджет [Form
][], в котором в качестве дочерних передаются виджеты [TextFormField
][] и кнопка submit. Виджет TextFormField
имеет параметр [onSaved
][], который принимает обратный вызов и выполняется при сохранении формы. Объект FormState
используется для сохранения, сброса или проверки каждого FormField
, являющегося потомком данной Form
. Для получения FormState
можно использовать Form.of()
с контекстом, предком которого является Form
, или передать конструктору Form
GlobalKey
и вызвать GlobalKey.currentState()
.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
В следующем примере показано, как Form.save()
и formKey
(который является GlobalKey
) используются для сохранения формы при отправке.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Код для конкретной платформы¶
При создании кроссплатформенного приложения необходимо использовать как можно больше кода для разных платформ. Однако могут возникнуть ситуации, когда в зависимости от ОС код должен быть разным. Это требует отдельной реализации с объявлением конкретной платформы.
В React Native для этого используется следующая реализация:
Javascript | |
---|---|
1 2 3 4 5 6 7 8 |
|
Во Flutter используйте следующую реализацию:
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 |
|
Отладка¶
Какие инструменты я могу использовать для отладки своего приложения во Flutter?¶
Для отладки приложений на Flutter или Dart используйте набор DevTools.
DevTools включает поддержку профилирования, изучения кучи, дерева виджетов, протоколирования диагностики, отладки, наблюдения за выполняемыми строками кода, отладки утечек памяти и фрагментации памяти. Более подробную информацию можно найти в документации DevTools.
Если вы используете IDE, вы можете отлаживать свое приложение с помощью отладчика IDE.
Как выполнить горячую перезагрузку?¶
Функция Stateful Hot Reload во Flutter помогает быстро и легко проводить эксперименты, создавать пользовательские интерфейсы, добавлять функции и исправлять ошибки. Вместо того чтобы перекомпилировать приложение каждый раз, когда вы вносите изменения, вы можете мгновенно выполнить горячую перезагрузку. Приложение обновляется, отражая внесенные изменения, а текущее состояние приложения сохраняется.
В React Native это сочетание клавиш ⌘R для симулятора iOS и двойное нажатие R в эмуляторах Android.
Во Flutter, если вы используете IntelliJ IDE или Android Studio, вы можете выбрать Save All (⌘s/ctrl-s) или нажать кнопку Hot Reload на панели инструментов. Если вы запускаете приложение из командной строки с помощью flutter run
, введите r
в окне Terminal. Вы также можете выполнить полный перезапуск, набрав R
в окне Терминала.
Как получить доступ к меню разработчика в приложении?¶
В React Native доступ к меню разработчика можно получить, встряхнув устройство: ⌘D для симулятора iOS или ⌘M для эмулятора Android.
Во Flutter, если вы используете IDE, вы можете воспользоваться инструментами IDE. Если вы запускаете свое приложение с помощью команды flutter run
, вы также можете получить доступ к меню, набрав h
в окне терминала, или набрать следующие сочетания клавиш:
Действие | Сокращение в терминале | Функции и свойства отладки |
---|---|---|
Иерархия виджетов приложения | w | debugDumpApp() |
Дерево рендеринга приложения | t | debugDumpRenderTree() |
Слои | L | debugDumpLayerTree() |
Доступность | S или U | debugDumpSemantics() |
Для переключения инспектора виджетов | i | WidgetsApp.showWidgetInspectorOverride |
Переключение отображения строительных линий | p | debugPaintSizeEnabled |
Для моделирования различных операционных систем | o | defaultTargetPlatform |
Для отображения наложения производительности | P | WidgetsApp.showPerformanceOverlay |
Чтобы сохранить снимок экрана в формате flutter.png | s | |
Уйти | q |
Анимация¶
Хорошо продуманная анимация делает пользовательский интерфейс интуитивно понятным, способствует улучшению внешнего вида и качества приложения, а также повышает удобство работы с ним. Поддержка анимации в Flutter позволяет легко реализовать простые и сложные анимации. Flutter SDK включает в себя множество виджетов Material Design, которые содержат стандартные эффекты движения, и вы можете легко настроить эти эффекты для персонализации вашего приложения.
В React Native для создания анимации используются Animated API.
Во Flutter для создания анимации используются класс [Animation
][] и класс [AnimationController
][]. Animation
- это абстрактный класс, который понимает свое текущее значение и состояние (завершено или отменено). Класс AnimationController
позволяет воспроизводить анимацию в прямом или обратном направлении, останавливать анимацию, а также устанавливать определенное значение для настройки движения.
Как добавить простую затухающую анимацию?¶
В приведенном ниже примере React Native с помощью Animated API создается анимированный компонент FadeInView
. Задаются начальное состояние непрозрачности, конечное состояние и длительность перехода. Анимационный компонент добавляется внутрь компонента Animated
, состояние непрозрачности fadeAnim
сопоставляется с непрозрачностью компонента Text
, который мы хотим анимировать, и затем вызывается start()
для запуска анимации.
Javascript | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
Чтобы создать такую же анимацию во Flutter, создайте объект [AnimationController
][] с именем controller
и укажите длительность. По умолчанию AnimationController
линейно генерирует значения в диапазоне от 0,0 до 1,0 в течение заданной длительности. Контроллер анимации генерирует новое значение каждый раз, когда устройство, на котором работает ваше приложение, готово отобразить новый кадр. Обычно эта скорость составляет около 60 значений в секунду.
При определении AnimationController
необходимо передать объект vsync
. Наличие vsync
не позволяет внеэкранной анимации потреблять лишние ресурсы. В качестве объекта vsync
можно использовать свой объект с состоянием, добавив в определение класса TickerProviderStateMixin
. Для AnimationController
необходим TickerProvider, который настраивается с помощью аргумента vsync
в конструкторе.
Объект [Tween
][] описывает интерполяцию между начальным и конечным значением или преобразование входного диапазона в выходной. Чтобы использовать объект Tween
с анимацией, вызовите метод animate()
объекта Tween
и передайте ему объект Animation
, который вы хотите изменить.
В данном примере используется виджет [FadeTransition
][], а свойство opacity
привязано к объекту animation
.
Чтобы запустить анимацию, используйте команду controller.forward()
. С помощью контроллера можно выполнять и другие операции, например fling()
или repeat()
. В данном примере виджет [FlutterLogo
][] используется внутри виджета FadeTransition
.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
|
Как добавить анимацию пролистывания карт?¶
В React Native для анимации пролистывания используется либо PanResponder
, либо сторонние библиотеки.
Во Flutter для добавления анимации пролистывания используется виджет [Dismissible
][] и вложенные дочерние виджеты.
Dart | |
---|---|
1 2 3 4 5 6 7 8 9 |
|
Эквивалентные компоненты виджетов React Native и Flutter¶
В следующей таблице перечислены часто используемые компоненты React Native, сопоставленные с соответствующими виджетами Flutter и общими свойствами виджетов.
React Native Component | Flutter Widget | Description |
---|---|---|
Button | [ElevatedButton ][] | A basic raised button. |
onPressed [required] | The callback when the button is tapped or otherwise activated. | |
Child | The button's label. | |
Button | [TextButton ][] | A basic flat button. |
onPressed [required] | The callback when the button is tapped or otherwise activated. | |
Child | The button's label. | |
ScrollView | [ListView ][] | A scrollable list of widgets arranged linearly. |
children | ( <Widget> [ ]) List of child widgets to display. | |
controller | [ [ScrollController ][] ] An object that can be used to control a scrollable widget. | |
itemExtent | [ double ] If non-null, forces the children to have the given extent in the scroll direction. | |
scroll Direction | [ [Axis ][] ] The axis along which the scroll view scrolls. | |
FlatList | [ListView.builder ][] | The constructor for a linear array of widgets that are created on demand. |
itemBuilder [required] | [[IndexedWidgetBuilder ][]] helps in building the children on demand. This callback is called only with indices greater than or equal to zero and less than the itemCount. | |
itemCount | [ int ] improves the ability of the ListView to estimate the maximum scroll extent. | |
Image | [Image ][] | A widget that displays an image. |
image [required] | The image to display. | |
Image. asset | Several constructors are provided for the various ways that an image can be specified. | |
width, height, color, alignment | The style and layout for the image. | |
fit | Inscribing the image into the space allocated during layout. | |
Modal | [ModalRoute ][] | A route that blocks interaction with previous routes. |
animation | The animation that drives the route's transition and the previous route's forward transition. | |
ActivityIndicator | [CircularProgressIndicator ][] | A widget that shows progress along a circle. |
strokeWidth | The width of the line used to draw the circle. | |
backgroundColor | The progress indicator's background color. The current theme's ThemeData.backgroundColor by default. | |
ActivityIndicator | [LinearProgressIndicator ][] | A widget that shows progress along a line. |
value | The value of this progress indicator. | |
RefreshControl | [RefreshIndicator ][] | A widget that supports the Material "swipe to refresh" idiom. |
color | The progress indicator's foreground color. | |
onRefresh | A function that's called when a user drags the refresh indicator far enough to demonstrate that they want the app to refresh. | |
View | [Container ][] | A widget that surrounds a child widget. |
View | [Column ][] | A widget that displays its children in a vertical array. |
View | [Row ][] | A widget that displays its children in a horizontal array. |
View | [Center ][] | A widget that centers its child within itself. |
View | [Padding ][] | A widget that insets its child by the given padding. |
padding [required] | [ EdgeInsets ] The amount of space to inset the child. | |
TouchableOpacity | [GestureDetector ][] | A widget that detects gestures. |
onTap | A callback when a tap occurs. | |
onDoubleTap | A callback when a tap occurs at the same location twice in quick succession. | |
TextInput | [TextInput ][] | The interface to the system's text input control. |
controller | [ [TextEditingController ][] ] used to access and modify text. | |
Text | [Text ][] | The Text widget that displays a string of text with a single style. |
data | [ String ] The text to display. | |
textDirection | [ [TextAlign ][] ] The direction in which the text flows. | |
Switch | [Switch ][] | A material design switch. |
value [required] | [ boolean ] Whether this switch is on or off. | |
onChanged [required] | [ callback ] Called when the user toggles the switch on or off. | |
Slider | [Slider ][] | Used to select from a range of values. |
value [required] | [ double ] The current value of the slider. | |
onChanged [required] | Called when the user selects a new value for the slider. |