Commit b80210db authored by Nicolas Richard Walter Boeckh's avatar Nicolas Richard Walter Boeckh 💬

Data pane UX/UI

UX/UI:
- Tweaked data tile (rounded corners)
- Tweaked settings layout (ListTile usage)

Fixes:
- Map display controller (null guard)

TODO: Make data pane only scrollable for data tiles.
parent 30e4190f
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_blue","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"geolocator","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\geolocator-5.2.1\\\\","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_api_availability-2.0.2\\\\","dependencies":[]},{"name":"location_permissions","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location_permissions-2.0.4+1\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.0\\\\","dependencies":[]},{"name":"permission_handler","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler-4.2.0+hotfix.3\\\\","dependencies":[]},{"name":"shared_preferences","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences-0.5.7+2\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"android":[{"name":"flutter_blue","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"geolocator","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\geolocator-5.2.1\\\\","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_api_availability-2.0.2\\\\","dependencies":[]},{"name":"location_permissions","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location_permissions-2.0.4+1\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.0\\\\","dependencies":[]},{"name":"permission_handler","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler-4.2.0+hotfix.3\\\\","dependencies":[]},{"name":"shared_preferences","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences-0.5.7+2\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"macos":[{"name":"shared_preferences_macos","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_macos-0.0.1+8\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"shared_preferences_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_web-0.1.2+5\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_blue","dependencies":[]},{"name":"geolocator","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","dependencies":[]},{"name":"location_permissions","dependencies":[]},{"name":"path_provider","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2020-08-20 22:54:47.792457","version":"1.21.0-10.0.pre.193"}
\ No newline at end of file
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_blue","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"geolocator","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\geolocator-5.2.1\\\\","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_api_availability-2.0.2\\\\","dependencies":[]},{"name":"location_permissions","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location_permissions-2.0.4+1\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.0\\\\","dependencies":[]},{"name":"permission_handler","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler-4.2.0+hotfix.3\\\\","dependencies":[]},{"name":"shared_preferences","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences-0.5.7+2\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"android":[{"name":"flutter_blue","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"geolocator","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\geolocator-5.2.1\\\\","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\google_api_availability-2.0.2\\\\","dependencies":[]},{"name":"location_permissions","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\location_permissions-2.0.4+1\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-1.6.0\\\\","dependencies":[]},{"name":"permission_handler","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\permission_handler-4.2.0+hotfix.3\\\\","dependencies":[]},{"name":"shared_preferences","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences-0.5.7+2\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"macos":[{"name":"shared_preferences_macos","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_macos-0.0.1+8\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-1.2.0\\\\","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"shared_preferences_web","path":"C:\\\\src\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\shared_preferences_web-0.1.2+5\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_blue","dependencies":[]},{"name":"geolocator","dependencies":["google_api_availability","location_permissions"]},{"name":"google_api_availability","dependencies":[]},{"name":"location_permissions","dependencies":[]},{"name":"path_provider","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2020-08-21 09:20:35.704809","version":"1.21.0-10.0.pre.212"}
\ No newline at end of file
......@@ -96,6 +96,7 @@ class MapDisplayController {
this._controller = new MapController();
/// This function is hooked to the [PositionHandler]s progress, ie. when a new [Position] is acquired (once per second), it is broadcasted across the app and can be listened to.
// TODO Fix this to allow external data (bounded map data)
PositionHandler().getCurrentOrLastPosition().listen((posChanged) {
if (posChanged == null)
return;
......@@ -134,16 +135,20 @@ class MapDisplayController {
if (latest != null) {
switch (_pmSymbol) {
case PMSymbol.PM1:
this.addToList(this._currentPos, latest.pm1(), 200);
if (latest.pm1() != null)
this.addToList(this._currentPos, latest.pm1(), 200);
break;
case PMSymbol.PM1:
this.addToList(this._currentPos, latest.pm2_5(), 200);
case PMSymbol.PM2_5:
if (latest.pm2_5() != null)
this.addToList(this._currentPos, latest.pm2_5(), 200);
break;
case PMSymbol.PM4:
this.addToList(this._currentPos, latest.pm4(), 200);
if (latest.pm4() != null)
this.addToList(this._currentPos, latest.pm4(), 200);
break;
case PMSymbol.PM10:
this.addToList(this._currentPos, latest.pm10(), 200);
if (latest.pm10() != null)
this.addToList(this._currentPos, latest.pm10(), 200);
break;
default:
break;
......
......@@ -94,14 +94,14 @@ class DataHandler {
Stream<DataPacket> getDataStream() async* {
while(true) {
yield (_sortedData.length > 0) ? _sortedData.last : null;
await Future.delayed(Duration(milliseconds: 500));
await Future.delayed(Duration(seconds: 1));
}
}
Stream<DataPacket> getMockDataStream() async* {
while(true) {
yield new DataPacket.fromData(1597957282000, 5, 42, 420, 3.0, 32, 24, 10123, 32, null, 5, null, 9, "");
await Future.delayed(Duration(milliseconds: 500));
await Future.delayed(Duration(seconds: 1));
}
}
......
......@@ -12,7 +12,7 @@ class BluetoothButton extends StatefulWidget {
BluetoothButton({Key key}) : super(key: key);
@override
_BluetoothButtonState createState() => _BluetoothButtonState();
_BluetoothButtonState createState() => _BluetoothButtonState(key: key);
}
class _BluetoothButtonState extends State<BluetoothButton> {
......
......@@ -11,7 +11,7 @@ class BluetoothDialog extends StatefulWidget {
BluetoothDialog({Key key}) : super(key: key);
@override
_BluetoothDialogState createState() => _BluetoothDialogState();
_BluetoothDialogState createState() => _BluetoothDialogState(key: key);
}
class _BluetoothDialogState extends State<BluetoothDialog> {
......
......@@ -15,11 +15,15 @@ class DataTile extends StatefulWidget {
/// [Stream] of [DataPacket] that tracks the newly received packets.
final Stream<DataPacket> stream;
DataTile(this.stream, {Key key}) : super(key: key);
final bool isDistant;
final String locationName;
DataTile(this.stream, this.isDistant, this.locationName, {Key key}) : super(key: key);
/// Provides [stream] to the [_DataTileState]
@override
State<DataTile> createState() => _DataTileState(this.stream);
State<DataTile> createState() => _DataTileState(this.stream, this.isDistant, this.locationName);
}
/// [State] of a [DataTile] displaying [stream] specific data.
......@@ -27,6 +31,10 @@ class _DataTileState extends State<DataTile> {
/// [Stream] of [DataPacket] that tracks the newly received packets.
final Stream<DataPacket> stream;
final bool isDistant;
final String locationName;
/// Value of the PM1 metric.
double _pm1 = -1;
......@@ -49,7 +57,7 @@ class _DataTileState extends State<DataTile> {
double _relativeHumidity = -1;
/// Creates a [_DataTileState] that listens to [stream] and changes the state whenever a new [DataPacket] is available.
_DataTileState(this.stream, {Key key}) {
_DataTileState(this.stream, this.isDistant, this.locationName) {
stream.listen((DataPacket newPacket) {
// Checks that the packet contains actual data.
if (newPacket != null && this.mounted)
......@@ -67,13 +75,16 @@ class _DataTileState extends State<DataTile> {
@override
Widget build(BuildContext context) {
// TODO Doc
/// This builds an indicator for a specific PM value, with appropriate AQI color scheme
Widget _buildPMDataCell(PMSymbol cellTitle, double value) => Expanded(
flex: 1,
child: Container(
color: (value != -1 && value != null) ? cellTitle.colorizeValue(value) : Colors.white,
margin: EdgeInsets.all(2),
padding: EdgeInsets.symmetric(vertical: 3),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: (value != -1 && value != null) ? cellTitle.colorizeValue(value) : Colors.white,
),
child: Column(
children: [
Text(
......@@ -85,7 +96,7 @@ class _DataTileState extends State<DataTile> {
Text(
(value != -1 && value != null) ? value.toString() : 'N/A',
style: TextStyle(
fontSize: 14,
fontSize: 16,
fontWeight: FontWeight.bold
),
)
......@@ -104,7 +115,7 @@ class _DataTileState extends State<DataTile> {
child: Text(
title,
style: TextStyle(
fontSize: 12,
fontSize: 14,
),
),
)
......@@ -114,14 +125,17 @@ class _DataTileState extends State<DataTile> {
Widget _buildEnvironmentalDataCells(double value) => Expanded(
flex: 1,
child: Container(
color: Colors.grey,
alignment: Alignment.center,
margin: EdgeInsets.all(2),
padding: EdgeInsets.symmetric(vertical: 3),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: (value != -1 && value != null) ? Colors.grey[200] : Colors.white,
),
child: Text(
(value != -1 && value != null) ? value.toString() : 'N/A',
style: TextStyle(
fontSize: 14,
fontSize: 16,
fontWeight: FontWeight.bold
),
)
......@@ -129,10 +143,26 @@ class _DataTileState extends State<DataTile> {
);
return Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(width: (this.isDistant) ? 1 : 0, color: Theme.of(context).dividerColor)
)
),
margin: EdgeInsets.symmetric(horizontal: 3),
child: Column(
children: [
Text("Area Title"),
(this.isDistant != null && this.locationName != null && this.isDistant) ? (
Container(
padding: EdgeInsets.symmetric(vertical: 3),
child: Text(
'Location: ${this.locationName}',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold
)
)
)
) : Container(width: 0, height: 0),
Row(
children: [
Expanded(
......
......@@ -3,7 +3,6 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:logair_application/logic/handlers/database_handler.dart';
import 'package:logair_application/logic/handlers/preference_handler.dart';
import 'package:logair_application/ui/base_widget.dart';
/// This [Widget] is a [Form] that enables users to change settings.
/// It interacts with the [PreferencesHandler] to affect changes that will be maintained on app restart.
......@@ -72,17 +71,15 @@ class _SettingsFormState extends State<SettingsForm> {
ListTile(title: Text('TODO: Push on 3G/4G')),
],
),
Divider(color: Colors.black,),
// CACHING
ExpansionTile(
title: Text('Local Data'),
initiallyExpanded: true,
leading: Icon(Icons.storage),
children: [
_buildActionTile('Delete local data\nOperation is final', () => DatabaseHandler().recreateDB())
ListTile(title: _buildActionTile('Delete local data', 'Operation is final', 'Delete', () => DatabaseHandler().recreateDB()))
],
),
Divider(color: Colors.black,),
// BLUETOOTH
ExpansionTile(
title: Text('Bluetooth'),
......@@ -112,11 +109,10 @@ class _SettingsFormState extends State<SettingsForm> {
),
),
// TODO Service / Characteristic Explorer ?
_buildInputTile(_bleServiceController, 'BLE Service UUID', 'BT.SERVICE_UUID', _advancedBTOptions, TextInputType.text, <TextInputFormatter>[ ], RegExp('[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}')),
_buildInputTile(_bleCharacteristicController, 'BLE Characteristic UUID', 'BT.CHARACTERISTIC_UUID', _advancedBTOptions, TextInputType.text, <TextInputFormatter>[ ], RegExp('[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}')),
ListTile(title: _buildInputTile(_bleServiceController, 'BLE Service UUID', 'BT.SERVICE_UUID', _advancedBTOptions, TextInputType.text, <TextInputFormatter>[ ], RegExp('[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}'))),
ListTile(title: _buildInputTile(_bleCharacteristicController, 'BLE Characteristic UUID', 'BT.CHARACTERISTIC_UUID', _advancedBTOptions, TextInputType.text, <TextInputFormatter>[ ], RegExp('[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}'))),
],
),
Divider(color: Colors.black,),
// MAP
ExpansionTile(
title: Text('Map'),
......@@ -149,8 +145,8 @@ class _SettingsFormState extends State<SettingsForm> {
),
),
),
_buildInputTile(_mapQueryLimitController, 'Maximum other points', 'MAP.PROX.MAX_PER_QUERY', _advancedMapOptions, TextInputType.number, <TextInputFormatter>[ FilteringTextInputFormatter.allow('0-9') ], RegExp(r'\d+')),
_buildInputTile(_mapQueryAgeController, 'Maximum age of other points (seconds)', 'MAP.PROX.MAX_AGE_SECONDS', _advancedMapOptions, TextInputType.number, <TextInputFormatter>[ FilteringTextInputFormatter.allow('0-9') ], RegExp(r'\d+')),
ListTile(title: _buildInputTile(_mapQueryLimitController, 'Maximum other points', 'MAP.PROX.MAX_PER_QUERY', _advancedMapOptions, TextInputType.number, <TextInputFormatter>[ FilteringTextInputFormatter.allow('0-9') ], RegExp(r'\d+'))),
ListTile(title: _buildInputTile(_mapQueryAgeController, 'Maximum age of other points (seconds)', 'MAP.PROX.MAX_AGE_SECONDS', _advancedMapOptions, TextInputType.number, <TextInputFormatter>[ FilteringTextInputFormatter.allow('0-9') ], RegExp(r'\d+'))),
],
),
],
......@@ -162,7 +158,7 @@ class _SettingsFormState extends State<SettingsForm> {
Row(
children: [
Expanded(
flex: 1,
flex: 1,
child: RaisedButton(
onPressed: () {
print(_formKey.currentState.validate());
......@@ -173,17 +169,28 @@ class _SettingsFormState extends State<SettingsForm> {
PreferencesHandler().setPreferencesBool('MAP.USING_ADVANCED', _advancedMapOptions);
}
},
child: Text('Confirm Changes'),
child: Text(
'Confirm Changes',
style: TextStyle(
fontSize: 18
)
),
),
),
Expanded(
flex: 1,
child: RaisedButton(
padding: EdgeInsets.zero,
onPressed: () async {
PreferencesHandler().resetAllPreferences();
_formKey.currentState.reset();
},
child: Text('Reset values'),
child: Text(
'Reset values',
style: TextStyle(
fontSize: 18
)
),
),
),
],
......@@ -198,7 +205,6 @@ class _SettingsFormState extends State<SettingsForm> {
Widget _buildInputTile(TextEditingController controller, String labelText, String key, bool enabled, TextInputType inputType, List<TextInputFormatter> inputFormatters, RegExp validation) {
PreferencesHandler().getPreferences(key).then((value) => controller.text = value.toString());
return Container(
padding: EdgeInsets.symmetric(vertical: 3, horizontal: 10),
child: Row(
children: [
Expanded(
......@@ -238,13 +244,19 @@ class _SettingsFormState extends State<SettingsForm> {
);
}
Widget _buildActionTile(String labelText, Function action) {
Widget _buildActionTile(String labelText, String warningText, String buttonText, Function action) {
return Container(
padding: EdgeInsets.symmetric(vertical: 1, horizontal: 10),
child: Row(
children: [
Expanded(
flex: 3,
child: Text(labelText)
),
Expanded(
flex: 2,
child: RaisedButton(
child: Text(labelText),
child: Text(buttonText),
onPressed: action
)
)
......
......@@ -16,7 +16,7 @@ class Graph extends StatefulWidget {
}
class _GraphState extends State<Graph> {
_GraphState({Key key}) {
_GraphState() {
GraphController().getGraphData().listen((Map<String, dynamic> newData) {
if (this.mounted) {
setState(() {
......
......@@ -30,6 +30,7 @@ class Indicator extends StatelessWidget {
decoration: BoxDecoration(
shape: isSquare ? BoxShape.rectangle : BoxShape.circle,
color: color,
borderRadius: BorderRadius.circular(3)
),
),
const SizedBox(
......
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:geolocator/geolocator.dart';
import 'package:logair_application/logic/handlers/data_handler.dart';
import 'package:logair_application/logic/handlers/position_handler.dart';
import 'package:logair_application/ui/carousel_card.dart';
import 'package:logair_application/ui/components/data_tile.dart';
import 'package:logair_application/ui/components/graph/graph.dart';
......@@ -19,7 +17,7 @@ class DataWidget extends StatelessWidget {
children: [
// Local data (Chart + Data points)
Graph(),
DataTile(DataHandler().getDataStream()),
DataTile(DataHandler().getDataStream(), false, ''),
// Bar (Locations + Add new -> Pop to new route)
Container(
color: Colors.grey,
......@@ -33,23 +31,23 @@ class DataWidget extends StatelessWidget {
),
IconButton(
onPressed: () => {},
icon: Icon(Icons.add),
icon: Icon(Icons.add),
)
],
),
),
SingleChildScrollView(
child: Column(
children: [
DataTile(DataHandler().getMockDataStream()),
DataTile(DataHandler().getMockDataStream()),
DataTile(DataHandler().getMockDataStream()),
DataTile(DataHandler().getMockDataStream()),
DataTile(DataHandler().getMockDataStream()),
DataTile(DataHandler().getMockDataStream()),
DataTile(DataHandler().getMockDataStream()),
],
),
Column(
children: [
DataTile(DataHandler().getMockDataStream(), true, 'Home'),
DataTile(DataHandler().getMockDataStream(), true, 'Work'),
DataTile(DataHandler().getMockDataStream(), true, 'C'),
DataTile(DataHandler().getMockDataStream(), true, 'D'),
DataTile(DataHandler().getMockDataStream(), true, 'E'),
DataTile(DataHandler().getMockDataStream(), true, 'F'),
DataTile(DataHandler().getMockDataStream(), true, 'G'),
DataTile(DataHandler().getMockDataStream(), true, 'H'),
DataTile(DataHandler().getMockDataStream(), true, 'I'),
],
),
],
)
......
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:logair_application/logic/data_packet.dart';
import 'package:logair_application/logic/handlers/database_handler.dart';
import 'package:logair_application/ui/animation/forward_animation.dart';
import 'package:logair_application/ui/base/header.dart';
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment