Эта статья написана для Android-разработчиков, которые хотят применить свои существующие знания для создания мобильных приложений с помощью Flutter. В этой статье мы рассмотрим эквивалент Activity во Flutter.
Предварительные требования
Предполагается, что вы уже настроили Flutter на своём ПК и можете запустить приложение «Hello World». Если нет, то сделайте это.
Dart основан на концепции ООП, поэтому Android-разработчику не составит труда начать использовать его.
Цель
В конце статьи мы сможем создавать пользовательский интерфейс для Activity, используя Flutter-виджеты, который будет выглядеть так:
Вообще, если вы заглянете внутрь Android-проекта, сгенерированного с помощью Flutter и откроете файл AndroidMenifest.xml
, то вы обнаружите, что там находится всего одна Activity, например, FlutterActivity
. Но в этой статье мы сосредоточимся на проектировании пользовательского интерфейса для Activity во Flutter. Как? При помощи scaffold (англ. строительные леса).
Scaffold
Scaffold — это набор виджетов, которые визуально представляют собой пользовательский интерфейс для Activity. Как правило, Activity используется для отображения одного экрана, который состоит из многих View-компонентов, таких как тулбар, меню, боковое меню, снэк-бар, FAB и т.д. А FrameLayout
используется как контейнер для фрагментов в Activity. В scaffold всё это представлено в виде виджетов.
Запомните, любой компонент во Flutter — виджет.
Изображение выше наглядно демонстрирует составляющие scaffold, который предоставляет API для отображения боковых меню, нижней панели, тулбара, области контента.
Поскольку scaffold — это material-виджеты, то они должны наследоваться от каких-то других material-компонентов, но мы обсудим это более подробно в других статьях. Сейчас мы сосредоточимся на создании scaffold-виджета.
import 'package:flutter/material.dart';
void main() => runApp(new MaterialApp(
home: new Scaffold(
),
));
Когда вы запустите этот код, вы увидите белый пустой экран, потому что вы ещё ничего не добавили в scaffold. Поэтому давайте определим цвет фона при помощи свойства backgroundColor
и установим жёлтый цвет:
void main() => runApp(new MaterialApp(
home: new Scaffold(
backgroundColor: Colors.yellowAccent,
),
));
Теперь вы увидите полностью жёлтый экран вашего приложения. Вы можете поиграться с другими свойствами scaffold, полный список которых можете найти в официальной документации.
Теперь мы знаем, как создать scaffold. Давайте исследуем его основные свойства одно за другим.
1. AppBar (Toolbar)
AppBar по сути тот же Toolbar
, который мы используем в нашей Activity. На картинке показано, где отображаются свойства AppBar.
-
leading: виджет, который отображается перед заголовком. Это может быть иконка гамбургер-меню или кнопка «Назад».
-
title: заголовок тулбара, обёрнутый в виджет
Text
. -
actions: это эквивалент
menu.xml
, в котором мы создаём набор<item/>
для отображения пунктов меню. Свойство actions принимает список виджетов для отображения в меню. Обычно этими виджеты представлены в виде IconButtons, которые эквивалентны<item/>
. -
bottom: обычно используется для
TabBar
, располагающегося под AppBar. -
flexibleSpace: этот виджет используется для создания эффекта
CollapsingToolbarLayout
(схлопывающегося тулбара).
Таким образом, вы можете создать простой Appbar с иконкой, заголовком и меню:
import 'package:flutter/material.dart';
void main() => runApp(new MaterialApp(
home: new Scaffold(
backgroundColor: Colors.yellowAccent,
appBar: new AppBar(
leading: new Icon(Icons.menu),
title: new Text("My Title"),
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.shopping_cart),
onPressed: () {},
),
new IconButton(
icon: new Icon(Icons.monetization_on),
onPressed: () {},
)
],
),
),
));
Это полученный результат. Выглядит точно так же, как обычный тулбар, который мы используем обычно. Вы можете поэкспериментировать с добавлением или удалением виджетов, добавлением стиля или цвета конкретному виджету.
В качестве практического упражнения можете изучить остальные свойства AppBar и поработать с ними.
2. Body (контейнер для любого View-компонента)
Это главная составляющая scaffold. Она работает так же, как Fragment Container в Android. Для отображения в области контейнера требуется виджет. Это область, где мы отображаем пользователю основной контент. В нашем примере для простоты мы добавим красный цвет в body. В реальной жизни кроме цвета фона используется множество других виджетов, например, ListView, Row, Column, Stack и т.д.
import 'package:flutter/material.dart';
void main() => runApp(new MaterialApp(
home: new Scaffold(
backgroundColor: Colors.yellowAccent,
appBar: new AppBar(
leading: new Icon(Icons.menu),
title: new Text("My Title"),
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.shopping_cart),
onPressed: () {},
),
new IconButton(
icon: new Icon(Icons.monetization_on),
onPressed: () {},
)
],
),
body: new Container(
color: Colors.red,
),
),
));
Body отображается позади AppBar, FAB и бокового меню. Несмотря на то, что мы применили желтый фон к scaffold, на экране отображается красный цвет body, перекрывающий фон scaffold.
3. Drawer (DrawerLayout)
Этот виджет представляет собой DrawerLayout
в Android, который выезжает из левой части Activity для отображения навигационных ссылок приложения.
Drawer обычно используется со свойством Scaffold.drawer. Как и в Android, мы используем NavigationView
внутри DrawerLayout
. В таблице ниже показаны эквивалентные View-компоненты в Android и Flutter.
Дочерним компонентом виджета Drawer обычно является ListView, чей первый элемент — DrawerHeader, который отображает информацию о текущем пользователе. Остальные элементы списка, как правило, создаются с помощью ListTiles. Следующий код показывает, каким образом создаётся Drawer:
import 'package:flutter/material.dart';
void main() => runApp(new MaterialApp(
home: new Scaffold(
backgroundColor: Colors.yellowAccent,
appBar: new AppBar(
title: new Text("My Title"),
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.shopping_cart),
onPressed: () {},
),
new IconButton(
icon: new Icon(Icons.monetization_on),
onPressed: () {},
)
],
),
drawer: new Drawer(
child: new ListView(
children: <Widget>[
new DrawerHeader(
child: new Text("Drawer Header"),
decoration: new BoxDecoration(
color: Colors.blue,
),
),
new Text("Item 1"),
new Text("Item 2"),
new Text("Item 3"),
new Text("Item 4"),
new Text("Item 5"),
new Text("Item 6"),
],
),
),
),
));
Вот такой результат вы должны получить. Стоит отметить, что при добавлении в scaffold виджета Drawer в AppBar автоматически добавляется иконка гамбургер-меню, поэтому все другие иконки стоит удалить.
Для получения дополнительной информации об этом виджете вы можете ознакомиться с практическим примером из документации или посвящённой этой теме отдельной статье.
4. BottomNavigationBar (BottomNavigationView)
Material-виджет, отображаемый в нижней части приложения, BottomNavigationBar состоит из нескольких элементов в виде текста и иконок.
BottomNavigationBar обычно применяется при помощи свойства Scaffold.bottomNavigationBar.
В Android вы определяете пункты меню в BottomNavigationView
с помощью свойства app:menu="@menu/my_navigation_items"
, где my_navigation_items
— это список всех пунктов меню в теге <item/>
. Во Flutter используется свойство items
, которое принимаете в качестве аргумента список BottomNavigationBarItem
, каждый из которых состоит из иконки, заголовка и цвета фона в меню.
import 'package:flutter/material.dart';
void main() => runApp(new MaterialApp(
home: new Scaffold(
backgroundColor: Colors.yellowAccent,
appBar: ...,
body:...,
drawer: ...,
bottomNavigationBar: new BottomNavigationBar(items: [
new BottomNavigationBarItem(
icon: new Icon(Icons.home),
title: new Text("Home"),
),
new BottomNavigationBarItem(
icon: new Icon(Icons.search),
title: new Text("Search"),
)
]),
),
));
Теперь у нас есть BottomNavigationBar с двумя пунктами меню.
Для обработки клика и изменения контента в scaffold нужен виджет поддерживающий сохранение состояния и некоторая ручная работа. Эта тема выходит за рамки этой статьи, но вы можете почитать об этом в официальной документации.
Кроме того, давайте добавим FAB в scaffold. Ниже представлен полный код для создания нашего пользовательского интерфейса Activity с помощью scaffold.
import 'package:flutter/material.dart';
void main() => runApp(new MaterialApp(
home: new Scaffold(
backgroundColor: Colors.yellowAccent,
appBar: new AppBar(
title: new Text("My Title"),
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.shopping_cart),
onPressed: () {},
),
new IconButton(
icon: new Icon(Icons.monetization_on),
onPressed: () {},
)
],
),
body: new Container(
color: Colors.red,
),
drawer: new Drawer(
child: new ListView(
children: <Widget>[
new DrawerHeader(
child: new Text("Drawer Header"),
decoration: new BoxDecoration(
color: Colors.blue,
),
),
new Text("Item 1"),
new Text("Item 2"),
new Text("Item 3"),
new Text("Item 4"),
new Text("Item 5"),
new Text("Item 6"),
],
),
),
bottomNavigationBar: new BottomNavigationBar(items: [
new BottomNavigationBarItem(
icon: new Icon(Icons.home),
title: new Text("Home"),
),
new BottomNavigationBarItem(
icon: new Icon(Icons.search),
title: new Text("Search"),
)
]),
floatingActionButton: new FloatingActionButton(
onPressed: (){},
child: new Icon(Icons.add),
),
),
));
Сейчас в FAB метод onPressed
не определён. Поэтому кнопка не будет реагировать на касания. При необходимости вы можете добавить обработку этого события.
Наконец, мы получили результат, о котором говорили в начале этой статьи.
Заключение
Flutter — мощный инструмент для быстрой разработки качественного, красивого пользовательского интерфейса. Он предоставляет множество виджетов для создания гибкого интерфейса с привлекательной анимацией. Scaffold — один из них, и это всего лишь верхушка айсберга. В следующих статьях рассмотрим другие темы.
Автор: Devcolibri
Спасибо за подробный разбор и объяснение С: я думаю, для совсем новчиков, которые еще только думают о том, чтобы взяться за флаттер, может быть полезен FAQ по Флаттеру