Статьи

Google Flutter с нуля: создание приложений с помощью виджетов

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 или выше

После установки нескольких облегченных плагинов вы можете использовать Android Studio, к которой привыкли разработчики приложений Android для среды IDE, для разработки приложений Flutter.

Начните с запуска Android Studio и выберите пункт « Настройка»> «Подключаемые модули» на экране приветствия.

В появившемся диалоговом окне нажмите кнопку « Обзор репозиториев» и найдите плагин Flutter.

Диалог просмотра репозиториев

Как только вы найдете плагин, нажмите кнопку « Установить» . На этом этапе вам будет предложено установить плагин Dart. Нажмите Да, чтобы продолжить.

Диалог зависимостей плагинов

После установки обоих плагинов нажмите кнопку « Перезагрузить Android Studio» , чтобы завершить настройку.

После перезагрузки вы увидите кнопку « Начать новый проект Flutter» на экране приветствия Android Studio. Нажмите, чтобы начать создание вашего первого проекта Flutter.

На следующем экране выберите опцию Flutter Application и нажмите Next .

Диалог создания флаттера

Теперь вы увидите форму, запрашивающую различные сведения о вашем приложении Flutter, такие как его название и местоположение. Убедитесь, что вы вводите допустимые значения во все поля.

Диалог конфигурации проекта Flutter

Плагин Flutter не входит в комплект Flutter SDK. Поэтому вы должны установить SDK отдельно. Вы можете сделать это, нажав кнопку Установить SDK сейчас.

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

В этом руководстве вы будете писать код внутри файла lib / main.dart . По умолчанию он будет содержать пример кода, который вам не понадобится. Поэтому удалите все его содержимое, прежде чем продолжить.

Платформа Flutter использует язык программирования Dart , простой в освоении язык, синтаксис которого очень похож на синтаксис Java и C. Следовательно, как и большинство автономных программ на Java и C, приложению Flutter также требуется функция main() , специальная функция, которая служит точкой входа в приложение.

Соответственно, добавьте следующий код в файл main.dart :

1
2
3
void main() {
    // TO DO
}

В этот момент вы можете нажать Shift-F10, чтобы создать и запустить приложение. Если вы не столкнулись с какими-либо ошибками на предыдущих шагах, вы должны увидеть, как приложение отображает пустой белый холст на вашем устройстве.

Все приложения Flutter состоят из одного или нескольких виджетов, экземпляров классов, которые позволяют рисовать текст и изображения на экране. Обычно вам не нужно программировать какие-либо низкоуровневые виджеты с нуля, потому что фреймворк поставляется с широким выбором готовых красивых виджетов, которые соответствуют языкам дизайна платформ Android и iOS.

Чтобы иметь возможность использовать базовые виджеты в вашем приложении, импортируйте библиотеку widgets , добавив следующий код в начало файла main.dart :

1
import ‘package:flutter/widgets.dart’;

Простейшие виджеты, которые вы можете создать — это виджеты без состояния Как вы уже догадались, они не имеют связанного с ними состояния и поэтому являются статичными. Они идеально подходят для отображения меток, заголовков и других элементов пользовательского интерфейса, содержимое которых вряд ли изменится во время работы приложения. Чтобы создать виджет без сохранения состояния, вы должны расширить класс StatelessWidget и переопределить его метод build() . В следующем примере кода показано, как:

1
2
3
4
5
6
class MyFirstWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // More code here
  }
}

Как видно из приведенного выше кода, метод build() должен возвращать объект Widget . Вы можете выбрать и вернуть любой из десятков готовых виджетов, предлагаемых Flutter. Например, если вы хотите отобразить строку текста, вы можете создать и вернуть Text виджет, как показано ниже:

1
2
return Text(«This is nice!»,
       textDirection: TextDirection.ltr);

Обратите внимание, что вы всегда должны указывать направление текста при использовании виджета « Text .

Однако, если вы запустите приложение сразу, вы не сможете увидеть текст. Это потому, что вы до сих пор не создали свой виджет без сохранения состояния. Поэтому перейдите к методу main() , создайте экземпляр виджета внутри него и передайте его runApp() . Вот как:

1
runApp(new MyFirstWidget());

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

Приложение показывает текст

Если вы хотите отобразить изображение вместо текста, вы можете просто заменить виджет « Text виджет « Image внутри метода build() вашего класса. Следующий код показывает, как создать виджет Image который загружает и отображает удаленное изображение:

1
2
return Image.network(
   «https://images.pexels.com/photos/1168940/pexels-photo-1168940.jpeg»);

При сохранении вашего проекта вы должны увидеть что-то вроде этого на вашем устройстве:

Приложение, показывающее изображение

Все приложения Flutter можно рассматривать как деревья виджетов. Приложение, которое вы создали на предыдущем шаге, представляет собой дерево виджетов с одним виджетом. Однако использование виджетов « Text или « Image в качестве верхних элементов дерева виджетов не является хорошей идеей, поскольку вы не сможете добавить к ним дочерние виджеты.

Flutter предлагает несколько виджетов, которые могут выступать в качестве контейнеров для других виджетов. Чаще всего используются виджеты Row и Column . Как видно из их названий, виджет « Row позволяет размещать несколько виджетов рядом друг с другом, а виджет « Column помогает расположить виджеты один под другим. Они незаменимы при создании более глубоких деревьев виджетов.

В следующем коде показано, как использовать виджет « Column для создания дерева виджетов, которое имеет двух дочерних Text виджет « Text виджет « Image .

1
2
3
4
5
6
7
8
9
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 :

1
2
3
4
5
return Center(child: Column(
    children: <Widget>[myText, myImage],
    mainAxisSize: MainAxisSize.min
  )
);

В приведенном выше коде обратите внимание, что виджет Column использует дополнительное свойство mainAxisSize , значение которого установлено в min . Это необходимо, поскольку перед центрированием столбца необходимо сделать его высоту равной сумме высот всех его дочерних элементов. Без свойства виджет « Column будет размером с экран устройства, а виджет « Center на него не повлияет.

Все это время вы использовали базовые виджеты, которые являются частью библиотеки widgets . Flutter имеет альтернативную библиотеку под названием material , которая предлагает виджеты Material Design. Чтобы использовать его в своем приложении, замените оператор, который импортирует библиотеку widgets следующим:

1
import ‘package:flutter/material.dart’;

Затем, чтобы применить стиль Material Design к вашим виджетам, вы должны иметь виджет MaterialApp в верхней части дерева виджетов. Вы также должны встроить все созданные ранее виджеты в виджет Scaffold , который может служить начальным экраном виджета MaterialApp .

Кроме того, поскольку большинство приложений Material Design имеют панель приложений, вы можете при желании установить свойство appBar виджета appBar на новый виджет AppBar .

Следующий код показывает, как сделать все это кратко:

01
02
03
04
05
06
07
08
09
10
11
return MaterialApp(
    home: Scaffold(
        appBar: AppBar(title: Text(«My App»)),
        body: Center(
          child: Column(
            children: <Widget>[myText, myImage],
            mainAxisSize: MainAxisSize.min
          ),
        )
    )
);

Приложение должно выглядеть намного лучше сейчас.

Приложение, отображающее виджеты Material Design

Виджеты без состояния являются неизменяемыми. С кодом, который вы написали на предыдущих шагах, нет простого способа изменить содержимое виджета « Text или виджета « Image . Почему? Потому что среда Flutter предпочитает реактивное программирование, а не императивное программирование. Следовательно, большинство его виджетов не имеют методов установки, которые могут обновлять их содержимое во время выполнения. Например, Text виджет не имеет метода setText() , который позволял бы вам изменять отображаемый текст.

Виджеты с состоянием, с другой стороны, являются изменяемыми, хотя и не напрямую. Они полагаются на объекты State чтобы решить, что они должны отображать в любом конкретном случае. Таким образом, всякий раз, когда изменяется объект State , платформа автоматически обновляет содержимое любого виджета с состоянием, связанного с ним.

Чтобы создать виджет с состоянием, вы должны расширить класс StatefulWidget и переопределить его createState() .

1
2
3
4
5
6
class MySecondWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TO DO
  }
}

Далее необходимо создать новый пользовательский класс State содержащий переменные, которые формируют состояние виджета с состоянием. Кроме того, внутри класса вы должны переопределить метод build() чтобы вернуть дерево виджетов.

Следующий код показывает, как создать класс State содержащий одну переменную с именем url :

01
02
03
04
05
06
07
08
09
10
class MyState extends State<MySecondWidget> {
 
  String url = «https://source.unsplash.com/random/800×600»;
              // A random image from Unsplash
 
  @override
  Widget build(BuildContext context) {
    // More code here
  }
}

Для конкретного примера давайте теперь создадим дерево виджетов Material Design, содержащее виджет Image , который отображает случайное изображение, и виджет RaisedButton , который пользователь может нажать, чтобы загрузить новое случайное изображение. Следующий код показывает вам, как:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
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() . Метод еще не существует, поэтому создайте его.

1
2
3
void changeURL() {
    // More code here
}

Внутри метода вы, конечно, должны изменить значение переменной url . Тем не менее, вы не должны менять это напрямую. Если вы это сделаете, платформа Flutter не будет уведомлена об изменении. Для корректного обновления состояния виджета с состоянием вы всегда должны вносить все изменения в метод setState() .

На данный момент, для отображения случайных изображений, я предлагаю вам использовать сервис Unsplash Source . Все, что вам нужно сделать, чтобы загрузить случайное изображение с него, это сделать HTTP-запрос к его URL и передать ему уникальную строку запроса.

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

1
2
3
4
setState(() {
  url = «https://source.unsplash.com/random/800×600/?»
      «q=${new DateTime.now().millisecondsSinceEpoch}»;
});

К этому моменту ваш пользовательский класс State готов. Все, что вам нужно сделать дальше, это создать его экземпляр и вернуть его из createState() вашего виджета с состоянием.

1
return MyState();

Если вы передадите экземпляр своего виджета с runApp() состояния в метод runApp() , перезагрузите приложение и несколько раз нажмите кнопку, вы должны увидеть, что он каждый раз отображает новую фотографию.

Приложение, отображающее случайные фотографии

Теперь вы знаете, как работать с виджетами без учета состояния и состояния в ваших приложениях Flutter. Вы также узнали, как применять к ним тему «Дизайн материалов», динамически изменять их содержимое и делать их интерактивными.

Стоит отметить, что Flutter не использует родные виджеты мобильной платформы. Он рисует все виджеты сам, используя высокопроизводительный графический движок 2D под названием Skia, который широко использует графический процессор. В результате приложения Flutter часто работают со скоростью около 60 кадров в секунду и чувствуют себя очень гибкими и отзывчивыми.

Чтобы узнать больше о виджетах во Flutter, обратитесь к официальной документации .