Экраны настроек

This commit is contained in:
Ivan Murashov
2017-09-11 14:51:50 +03:00
parent 0dde204dcd
commit 24fdfc15f6
21 changed files with 148 additions and 98 deletions

226
lib/base/base_state.dart Normal file
View File

@@ -0,0 +1,226 @@
import 'package:checker/resources.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:intl/intl.dart';
import 'package:checker/common.dart';
import 'package:checker/consts.dart';
import 'package:checker/screens/settings.dart';
import 'package:checker/screens/faq.dart';
import 'package:checker/strings.dart';
import 'package:checker/db.dart';
abstract class BaseState<T extends StatefulWidget> extends State<T> {
SqliteHelper helper;
/// Тип сборки. Определяет, какие брать ресурсы (цвета, картинки)
String app;
/// Ожидание ответа от сервера.
bool loading = false;
/// Текст ошибки, подставляется в подсказку, либо появляется над текстовым полем.
String error;
/// Введенное пользователем значение.
String dinCode = '';
@override Widget build(BuildContext ctx) {
if (helper == null) {
helper = new SqliteHelper();
helper.open().then((_) {
if (app == null) {
platform.invokeMethod('getFlavor').then((flavor) {
app = flavor;
setState(() {
onStart();
});
});
}
});
}
return getMainWidget();
}
Widget getMainWidget() {
return app == null ? getBackground() : new Scaffold(appBar: getAppBar(),
body: new Stack(children: <Widget>[
getScreenContent(),
new Center(child: loading ? new CircularProgressIndicator() : null)
]));
}
Widget getBackground() {
return new Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new ExactAssetImage(Resources.getSplash(app)),
fit: BoxFit.cover)));
}
void onStart() {
print("ON START!");
}
/// Возвращает контейнер с всеми виджетами экрана.
Widget getScreenContent();
/// Возвращает заголовок для AppBar
String getTitle() {
return null;
}
AppBar getAppBar() {
return new AppBar(title: new Text(getTitle(), style: new TextStyle(fontSize: 18.0)),
backgroundColor: Resources.getPrimaryColor(app), actions: getMenuButtons());
}
List<Widget> getMenuButtons() {
return <Widget>[
new PopupMenuButton<int>(
onSelected: onOptionsItemClick,
itemBuilder: (BuildContext context) {
return [new PopupMenuItem(
value: 0,
child: getMenuItem(settings_png, StringsLocalization.settings())),
new PopupMenuItem(
value: 1,
child: getMenuItem(help_png, StringsLocalization.help())),
new PopupMenuItem(
value: 2,
child: getMenuItem(logout_png, StringsLocalization.logout()))
];
}
)];
}
void onOptionsItemClick(int index) {
switch (index) {
case 0: {
pushRoute(context, new SettingsScreen());
break;
}
case 1: {
pushRoute(context, new FAQScreen(false));
break;
}
case 0: {
logout(context);
}
}
}
Widget getMenuItem(String image, String text) {
return new Row(children: [
new Image.asset(image, width: 28.0, height: 28.0),
new Container(padding: new EdgeInsets.only(left: 8.0), child: new Text(text))
]);
}
/// Возврвщает контейнер, внутри которого Text с подсказкой.
Widget getHintLabel() {
double horizontalMargin = 8.0;
return new Container(margin: new EdgeInsets.only(top: horizontalMargin, bottom: horizontalMargin, left: verticalMargin, right: verticalMargin),
child: new Row(crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[new Text(getHintString(), textAlign: TextAlign.left,
style: new TextStyle(fontWeight: FontWeight.w300, color: error == null ? greyTextColor : Resources.getLogo(app), fontSize: 14.0))]));
}
/// Возвращает подсказку, либо ошибку, если введенные в поле ввода данные неверны.
String getHintString() {
if (dinCode.length == 0 && error == null) {
return ' ';
} else if (error != null) {
return error;
} else {
return getHint();
}
}
/// Возвращает текст подсказки для поля ввода.
/// Должен быть переопределен на экранах, на которых есть поле ввода.
String getHint() {
return null;
}
/// Смена состояния экрана при изменении текста в поле ввода.
void handleUserInput(String text) {
setState(() {
dinCode = text;
});
}
/// Метод возвращает контейнер с полем ввода внутри.
Widget getInputField() {
return new Container(margin: new EdgeInsets.only(left: verticalMargin, right: verticalMargin),
padding: getInputFieldContainerPadding(),
decoration: getInputFieldContainerDecoration(),
child: getTextWidget());
}
/// Возвращает поле ввода.
/// Переопределяется для использования на экранах регистрации и проведения покупки.
Widget getTextWidget() {
return null;
}
/// Возвращат паддинги для поля ввода.
EdgeInsets getInputFieldContainerPadding() {
const double verticalPadding = 12.0;
const double horizontalPadding = 16.0;
return new EdgeInsets.only(top: verticalPadding,
bottom: verticalPadding,
left: horizontalPadding,
right: horizontalPadding);
}
/// Метод возвращает BoxDecoration для _getDecoratedInputField
BoxDecoration getInputFieldContainerDecoration() {
return new BoxDecoration(color: inputFieldBackground,
border: new Border.all(color: textBorderColor, width: 1.0),
borderRadius: new BorderRadius.all(new Radius.circular(4.0)));
}
/// Возвращает выпуклую залитую фирменным цветом кнопку
Widget buildRaisedButton(String text, VoidCallback onPressed) {
return new RaisedButton(child: new Text(text,
style: new TextStyle(color: Colors.white)),
onPressed: onPressed,
color: Resources.getButtonColor(app));
}
/// Метод возвращает контейнер с отступами, который содержит картинку с логотипом.
Widget getLogo() {
double containerHeight = 92.0;
double imageWidth = 156.0;
return new Container(height: containerHeight, child: new Image.asset(Resources.getLogo(app), width: imageWidth));
}
/// Возвращает текстовое поле, с однострочным пояснением над ним.
Widget getValueWithDescription(String title, String value) {
return new Container(padding: new EdgeInsets.only(left: verticalMargin, right: verticalMargin, top: 18.0),
child: new Column(children: <Widget>[
new Row(crossAxisAlignment: CrossAxisAlignment.start, children: getDescriptionWidget(title)),
new Row(crossAxisAlignment: CrossAxisAlignment.start, children: getValueWidget(value))
]));
}
/// Возвращает список, единственный элемент которого - Text с заголовком для текстового поля.
List<Widget> getDescriptionWidget(String title) {
return <Widget>[new Text(title, textAlign: TextAlign.left, style: new TextStyle(color: greyTextColor, fontSize: 14.0))];
}
/// Возвращает список, единственный элемент которого - Text с информацией (размер скидки, сумма проведенной покупки).
List<Widget> getValueWidget(String value) {
return <Widget>[new Expanded(child: new Text(value, textAlign: TextAlign.left, style: new TextStyle(color: Colors.black, fontSize: 20.0)))];
}
/// Возвращает кнопку, обернутую набором специфичных контейнеров.
Widget wrapButton(EdgeInsets margin, Widget widget) {
return new Container(margin: margin, height: buttonHeight, child: new Row(children: <Widget>[new Expanded(child: widget)]));
}
}

View File

@@ -0,0 +1,46 @@
import 'package:checker/base/base_state.dart';
import 'package:checker/consts.dart';
import 'package:checker/strings.dart';
import 'package:flutter/material.dart';
abstract class SettingsBaseState<T extends StatefulWidget> extends BaseState<T> {
@override
Widget getScreenContent() {
List<Widget> widgets = new List();
for (String option in getOptions()) {
widgets.add(getItem(option));
}
return new ListView(children: widgets);
}
List<String> getOptions();
@override
List<Widget> getMenuButtons() {
return null;
}
Widget getItem(String option) {
return new Container(
height: 56.0,
child: (new FlatButton(onPressed: null,
child: new Row(children: <Widget>[
new Expanded(child: new Text(option)),
getCheckMark()]))));
}
Widget getCheckMark() {
return new Image.asset(check_png,
width: 28.0,
height: 28.0);
}
@override
String getTitle() {
return StringsLocalization.settings();
}
}