Russian (Pусский) translation by Oleg Kiselevich (you can also view the original English article)
Flutter быстро становится одним из самых популярных фреймворков для разработки кросс платформенных мобильных приложений. Большинство разработчиков Android и iOS сегодня начинают соглашаться с тем, что это более быстрая и перспективная альтернатива другим кросс платформенным фреймворкам, таким как React Native и NativeScript.
Google из кожи вон лезет, чтобы привлечь к нему больше разработчиков. Например на Google I/O в этом году было несколько углубленных сессий, сосредоточенных на разработке с помощью него приложений, отвечающих принципам Material Design. Во время одной из сессий Google также объявил, что Flutter станет первоклассной платформой для Material Design.
В этой серии уроков я собираюсь помочь вам с основами разработки Android приложений на Flutter. В этом уроке, с которого начинается вся серия, я собираюсь сосредоточиться на виджетах Flutter, которые являются строительными блоками для создания всех Flutter приложений.
Необходимые условия
Чтобы эта серия уроков была для вас наиболее полезна, вам понадобится:
- последняя версия Android Studio
- устройство или эмулятор для запуска Android API версии 21 или выше
1. Настройки Android Studio
После установки нескольких небольших плагинов, вы можете использовать для разработки Flutter приложений Android Studio - IDE, к которой наиболее привыкли разработчики нативных Android приложений.
Сперва запустите Android Studio и выберете пункт меню Configure > Plugins (Конфигурация > Плагины) в приветственном окне.
В появившимся диалоговом окне нажмите кнопку Browse Repositories (Обзор репозиториев) и найдите плагин Flutter.

Когда нашли плагин, нажмите кнопку Install (Установить) для него. После этого вам будет задан вопрос о том, стоит ли также установить и плагин Dart. Нажмите Yes (Да) для продолжения.

После установки обоих плагинов нажмите кнопку Restart Android Studio (Перезапустить Android Studio) для завершения настроек.
2. Создание нового проекта
После перезапуска вы сможете увидеть кнопку Start a new Flutter project (Начать новый проект Flutter) в приветственном окне Android Studio. Нажмите ее для создания вашего первого проекта Flutter.
В следующем окне выберете опцию Flutter Application (Приложение Flutter) нажмите Next (Далее)

Вы теперь увидите форму для заполнения различных подробностей о Flutter приложении, например, желаемое название и расположение. Убедитесь, что вводите допустимые значения во всех полях.

Плагин Flutter не включает в себя Flutter SDK. Поэтому вам нужно установить SDK отдельно. Это можно сделать, нажав кнопку Install SDK (Установить SDK) в текущем окне.
В зависимости от скорости вашего соединения для завершения установки может потребоваться достаточно много времени. После успешного окончания вы сможете нажать кнопку Next (Далее) для завершения создания проекта.
3. Добавление точки входа
На протяжении этого урока вы будете писать код в файле lib/main.dart. По умолчанию он будет содержать некоторые примеры кода, которые вам не понадобятся. Так что перед началом редактирования удалите все его содержимое.
Фреймворк Flutter использует язык программирования Dart, который легко выучить и чей синтаксис очень похож на синтаксис Java и C. По примеру многих самостоятельных программ на Java и C, для Flutter необходима специальная функция main()
, которая служит точкой входа для всего приложения.
Соответственно, добавьте следующий код в файл main.dart:
void main() { // TO DO }
На данном этапе вы можете нажать Shift + F10, чтобы скомпилировать и запустить приложение. Если не возникло ошибок на предыдущих шагах, вы должны увидеть, что приложение отобразит пустой белый холст на вашем устройстве.
4. Использование виджетов, не имеющих указания состояния
Все Flutter приложения состоят из одного или более виджетов - экземпляров классов, которые позволяют рисовать текст и изображения на экране. Обычно вам не придется программировать какой-либо низкоуровневый виджет с нуля, поскольку фреймворк поставляется с широким спектром готовых красивых виджетов, которые поддерживают языки разработки платформ Android и iOS.
Чтобы иметь возможность использовать основные виджеты в вашем приложении, импортируйте библиотеку widgets
, добавив следующий код в начало файла main.dart:
import 'package:flutter/widgets.dart';
Простейшие виджеты, которые можно создать - это виджеты без указания состояния. Как вы уже догадались, с ними не связано состояние и таким образом они являются статическими. Они идеально подходят для отображения меток, названий и других элементов пользовательского интерфейса, содержание которых вряд ли изменится во время работы приложения. Для создания статического виджета, необходимо расширить класс StatelessWidget
и переопределить его метод build()
. В следующем примере кода показано, как:
class MyFirstWidget extends StatelessWidget { @override Widget build(BuildContext context) { // More code here } }
Как вы можете видеть в приведенном выше коде, метод build()
должен возвращать объект Widget
. Вы можете выбрать и возвращать любой из десятков готовых виджетов, доступных в Flutter. Например, если вы хотите отобразить строку текста, можно создать и возвратить виджет Text
, как показано ниже:
return Text("This is nice!", textDirection: TextDirection.ltr);
Обратите внимание, что вы всегда должны задавать направление текста при использовании виджета Text
.
Однако, если вы запустите приложение прямо сейчас, вы не сможете увидеть текст. Это потому, что вы до сих пор не вызвали этот статический виджет. Итак, перейдите в метод main()
, вызовите виджет внутри него и передайте его методу runApp()
. Вот как:
runApp(new MyFirstWidget());
В тот момент, как вы добавите приведенный выше код и сохраните ваш проект, Android Studio должна автоматически перезагрузить приложение на вашем устройстве, что позволит увидеть текст.

Если вы хотите отобразить изображение вместо текста, вы можете просто заменить виджет Text
на виджет Image
внутри метода build()
вашего класса. Следующий код показывает, как создать виджет Image
, который загружает и отображает удаленное изображение:
return Image.network( "https://images.pexels.com/photos/1168940/pexels-photo-1168940.jpeg");
И снова, после сохранения вашего проекта, вы должны увидеть что-то вроде этого на вашем устройстве:

5. Создание деревьев виджетов
Любое приложение Flutter можно воспринимать как дерево виджетов. Приложение, которое вы создали на предыдущем шаге, - это дерево виджетов, имеющее всего один виджет. Использование Text
или Image
виджетов как элементов верхнего уровня дерева виджетов не является хорошей идеей, потому что вы не сможете добавлять для них дочерние виджеты.
Flutter предлагает несколько виджетов, которые могут выступать в качестве контейнеров для других виджетов. Наиболее часто используемыми из них являются виджеты Row
и Column
. Как следует из названия, виджет Row
позволяет размещать несколько виджетов рядом друг с другом, а виджет Column
поможет вам разместить виджеты один под другим. Они незаменимы при создании многоуровневых деревьев виджетов.
Следующий код показывает, как использовать виджет Column
для создания дерева виджетов, которое имеет два дочерних элемента: виджет Text
и виджет Image
.
Text myText = Text("This is a nice photo!", textDirection: TextDirection.ltr); Image myImage = Image.network( "https://images.pexels.com/photos/1168940/pexels-photo-1168940.jpeg"); return Column( children: <Widget>[myText, myImage] );
Теперь приложение должно выглядеть следующим образом:

Кроме того, есть виджеты, которые служат для правильного расположения другого виджета. К примеру, виджет Center
помогает вам расположить виджет по центру. Аналогично виджет Container
позволяет добавлять отступы и поля для виджетов.
Следующий код показывает, как отцентрировать виджет Column
, который вы только что создали, внедрив его внутрь виджета Center
:
return Center(child: Column( children: <Widget>[myText, myImage], mainAxisSize: MainAxisSize.min ) );
В приведенном выше коде обратите внимание, что виджет Column
использует дополнительное свойство под названием mainAxisSize
, значение которого задано в min
. Это необходимо потому, что, прежде чем отцентрировать столбец, вы должны сделать его высоту равной сумме высот всех его дочерних элементов. Без такого свойства виджет Column
будет иметь такой же размер, как экран устройства, и виджет Center
не будет иметь никакого эффекта на него.
6. Использование виджетов Material Design
Все это время вы использовали основные виджеты, которые являются частью библиотеки widgets
. Flutter имеет альтернативную библиотеку под названием material
, которая предлагает виджеты Material Design. Чтобы использовать ее в вашем приложении, измените инструкцию, которая импортирует библиотеку widgets
следующим образом:
import 'package:flutter/material.dart';
Далее, чтобы применить стиль Material Design к вашим виджетам, вы должны иметь виджет MaterialApp
в верхней части вашего дерева виджетов. Необходимо также внедрить все ранее созданные виджеты внутрь виджета Scaffold
, который может служить в качестве домашнего экрана виджета MaterialApp
.
Кроме того, поскольку большинство приложений Material Design имеют панель приложения, можно дополнительно указать в качестве значения свойства appBar
виджета Scaffold
новый виджет AppBar
.
Следующий код показывает, как лаконично выполнить все эти задачи:
return MaterialApp( home: Scaffold( appBar: AppBar(title: Text("My App")), body: Center( child: Column( children: <Widget>[myText, myImage], mainAxisSize: MainAxisSize.min ), ) ) );
Приложение должно теперь выглядеть гораздо лучше.

7. Использование виджетов с указанием состояния
Статические виджеты являются неизменяемыми. Код, который вы написали в предыдущих шагах, не имеет простого способа изменить содержимое виджета Text
или виджета Image
. Почему? Потому что фреймворк Flutter отдает предпочтение реактивному программированию над императивным программированием. Следовательно большинство его виджетов не имеют методов установки значений, которые позволяют обновлять их содержимое во время выполнения программы. Например, виджет Text
не имеет метода setText()
, который позволил бы изменить отображаемый текст.
Виджеты с отслеживанием состояния, напротив, являются изменяемыми, хотя и не напрямую. Они полагаются на объекты State
для определения, что они должны отображаться в той или иной ситуации. Таким образом, всякий раз, когда изменяется объект State
, фреймворк будет автоматически обновлять содержимое любого виджета с указанием состояния, подключенного к нему.
Чтобы создать виджет с указанием состояния, необходимо расширить класс StatefulWidget
и переопределить его метод createState()
.
class MySecondWidget extends StatefulWidget { @override State<StatefulWidget> createState() { // TO DO } }
Далее необходимо создать новый пользовательский класс State
, который содержит переменные, которые формируют состояние такого виджета. Кроме того, внутри класса необходимо переопределить метод build()
для возвращения вашего дерева виджетов.
Следующий код показывает, как создать класс State
, содержащий одну переменную url
:
class MyState extends State<MySecondWidget> { String url = "https://source.unsplash.com/random/800x600"; // A random image from Unsplash @override Widget build(BuildContext context) { // More code here } }
Ради примера создадим дерево виджетов Material Design, содержащее виджет Image
, который отображает случайное изображение, и виджет RaisedButton
, который пользователь может нажать, чтобы загрузить новое случайное изображение. В следующем коде показано, как:
return MaterialApp( home: Scaffold( body: Center( child:Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ RaisedButton( child: Text("Press Me"), onPressed: changeURL, ), Image.network(url) ] ) ) ) );
Обратите внимание, что конструктор виджета Image
теперь принимает переменную url
в качестве аргумента, вместо строкового значения. Это позволяет фреймворку использовать последнее значение переменной при каждом отображении виджета Image
.
Также, обратите внимание, что виджет RaisedButton
имеет атрибут onPressed
, который указывает на регистратор события changeURL()
. Сам метод еще не существует, так что создадим его.
void changeURL() { // More code here }
Внутри метода вы должны, конечно, изменить значение переменной url
. Однако вы не должны изменять его напрямую. Если вы это делаете, фреймворк Flutter не будет уведомлен об изменении. Для правильного обновления состояния виджета, вы всегда должны делать все ваши изменения внутри метода setState()
.
Для отображения случайных изображений, я предлагаю вам использовать службу Unsplash Source. Все, что вам нужно сделать, чтобы загрузить случайное изображение из него, - это отправить HTTP запрос на его URL-адрес и передать ему уникальную строку запроса.
Следующий код показывает, как сделать это с помощью штампа времени для построения уникальной строки запроса:
setState(() { url = "https://source.unsplash.com/random/800x600/?" + "q=${new DateTime.now().millisecondsSinceEpoch}"; });
Теперь ваш пользовательский класс State
готов. Все, что вам нужно сделать дальше — это создать его экземпляр и вернуть его из метода createState()
вашего виджета с отслеживанием состояния.
return MyState();
Если передать методу runApp()
экземпляр вашего виджета с отслеживанием состояния, перезагрузить приложение и нажать на кнопку несколько раз, вы должны увидеть, как каждый раз отображается новая фотография.

Заключение
Теперь вы знаете, как работать с виджетами как без указания состояния, так и с указанием состояния в приложениях Flutter. Вы также узнали, как применять к ним тему оформления Material Design, динамически изменять их содержимое и делать их интерактивными.
Стоит отметить, что Flutter не использует родные виджеты какой-либо мобильной платформы. Он создает все виджеты сам, используя высоко-производительный 2D графический движок Skia, который широко использует ресурсы GPU. В результате Flutter приложения часто выдают около 60 кадров в секунду и являются очень плавными и отзывчивыми в работе.
Чтобы узнать больше о виджетах в Flutter, обратитесь к официальной документации.
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post