В предыдущей статье мы подключили Flutter SDK и создали hello world приложение. Сейчас создадим простое приложение где реализуем экран авторизации, простой механизм валидации логина и пароля и если валидация пройдёт успешно, то осуществить переход на следующий экран:
Создадим новый проект как было описано в предыдущей статье. Заменим содержимое файл \lib\main.dart на представленный ниже код:
import 'package:flutter/material.dart';
void main() => runApp(
new MyApp(),
);
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(home: new Scaffold());
}
}
Как и в Java у Dart есть точка входа с которой начинается запуск программы - это метод main(). Нотация => предназначена для более наглядного представления вызова функций. Функция runApp предназначена для создания и вывода на экран виджета, который мы создаём и передаём в качестве параметра.
Класс MyApp наследуется от StatelessWidget тем самым получает свойства неизменяемого виджета. При наследовании нужно переопределить метод создания виджета build(BuildContext context). MaterialApp - создаёт приложение которое, реализует принципы material design. В качестве маршрута по умолчанию в параметре home передадим класс Scaffold(), который реализует основную структура макета.
Если запустить этот код, то на экране будет отображён пустой белый экран с пометкой debug в правом верхнем углу:
Теперь разместим визуальные компоненты на экране. Как мы помним из первой стать во flutter все визуальные компоненты являются виджетами. Благодаря взаимовложенности виджетов друг в друга и строиться графический интерфейс.
Сейчас у нас есть пустой экран, создадим два поля для ввода текста и кнопку login.
class MyApp extends StatelessWidget {
final _sizeTextBlack = const TextStyle(fontSize: 20.0, color: Colors.black);
final _sizeTextWhite = const TextStyle(fontSize: 20.0, color: Colors.white);
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Container(
child: new TextFormField(
decoration: new InputDecoration(labelText: "Email"),
keyboardType: TextInputType.emailAddress,
style: _sizeTextBlack,
),
width: 400.0,
),
new Container(
child: new TextFormField(
decoration: new InputDecoration(labelText: "Password"),
obscureText: true,
style: _sizeTextBlack,
),
width: 400.0,
padding: new EdgeInsets.only(top: 10.0),
),
new Padding(
padding: new EdgeInsets.only(top: 25.0),
child: new MaterialButton(
color: Theme
.of(context)
.accentColor,
height: 50.0,
minWidth: 150.0,
child: new Text(
"LOGIN",
style: _sizeTextWhite,
),
),
)
],
)
),
),
);
}
}
Для того что бы выронить все элементы по центру экрана воспользуемся классом Center (строка 9). Для расположения все элементы в один столбец необходимо использовать класс Column в котором для выравнивания дочерних элементов по центру задаём значение параметра mainAxisAlignment: MainAxisAlignment.center (строки 10-11).
В класс Column можно передать массив виджетов которые будут отображаться внутри него в вертикальном порядке друг под другом (строка 12). Каждое полу ввода нужно ограничить по ширине, поэтому необходимо “завернуть” всё это в ещё один класс Container. У которого уже можно задать нужный параметр width (строка 19). В качестве параметров стиля для текста создадим две переменные _sizeTextBlack и _sizeTextWhite (строки 2-3).
Для поля ввода Email зададим параметр типа клавиатуры TextInputType.emailAddress, а для поля пароля выставим obscureText в true (строка 16 и 24).
Для отображение кнопки нам понадобиться отступ который мы сможем задать через класс Padding (строка 30).
В итоге у нас получиться следующий результат:
Далее реализуем простую логику валидации почты и пароля. Для хранения и передачи данных создадим в классе MyApp две переменные _email и _password:
class MyApp extends StatelessWidget {
String _email;
String _password;
...
У виджета TextFormField есть метод onSaved который возвращает значение поля ввода при изменениях. Это значение сохраняем в переменные _email и _password соответственно. Так же есть функция validator в которой можно реализовать логику отображения подсказки в случае если валидация не пройдена.
child: new TextFormField(
...
onSaved: (val) => _email = val,
validator: (val) =>
!val.contains("@") ? 'Not a valid email.' : null,
...
),
Обработаем событие нажатие на кнопку. В виджет MaterialButton есть функция onPressed который вызывается после нажатие кнопки. Для лаконичности кода вынесем обработку нажатия в отдельный метод submit.
child: new MaterialButton(
onPressed: submit,
...
),
Для того что бы провалидировать сразу все поля нужно создать дополнительный виджет Form. У него есть тип key, который создаёт контейнер для полей формы. Его будем хранить в поле formKey.
class MyApp extends StatelessWidget {
...
final formKey = new GlobalKey<FormState>();
...
body: new Center(
child: new Form(
key: formKey,
child: new Column(
...
}
Реализуем метод submit(). В нём выполняется получение полей ввода и вызова метода validate():
void submit() {
final form = formKey.currentState;
if (form.validate()) {
form.save();
performLogin();
}
}
void performLogin() {
hideKeyboard();
Navigator.push(
_context,
new MaterialPageRoute(
builder: (context) => new SecondScreen(_email, _password)));
}
void hideKeyboard() {
SystemChannels.textInput.invokeMethod('TextInput.hide');
}
После успешной валидации скрываем клавиатуру и открываем экран в который передадим значение логина и пароля:
Весь код проекта можно посмотреть по ссылке.